[Scummvm-git-logs] scummvm master -> d38596820996de74746aceef369704706c27d870
dreammaster
noreply at scummvm.org
Fri May 6 05:43:18 UTC 2022
This automated email contains information about 26 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
edca3fcdea COMMON: Added move assignment operator to ScopedPtr
830c1b096b AGS: introduced ObjTexture struct which combines bmp and ddb
8e4254b839 AGS: Refactored walk-behinds calculation and texture generation
d161f11e54 AGS: Further simplify walkbehinds_cropout()
cfefb80461 AGS: Moved font renderer shutdown after the game data disposal
da1178d905 AGS: Implemented proper HasAlphaChannel for all gui controls
d767293a32 AGS: Updated build version (3.6.0.24)
480be2134b AGS: Added script instance thread stack, replacing current_instance
a2a5f2575d AGS: Reorganized few cc_ headers
16d0d89787 AGS: Grouped ccError variables in a struct
8e132f7b3f AGS: cc_error returns stack from all script threads
540a92a6c5 AGS: Necessary fixes to build with latest changes to ccError
faa858a55b AGS: Fixed sending non-error messages to debugger
6482e38803 AGS: CharacterExtras and MoveLists are stored in std::vector
a40ea44aa2 AGS: CharacterCache is stored in std::vector, hide in draw.cpp
97eb5271d3 AGS: Added member initialization for CharacterExtras, MoveList
a8ead540c5 AGS: GUIControl::CalcGraphicRect returns relative rect
28a2b6aa9c AGS: Added extra checks for abort_engine being set
63c42d42c3 AGS: Fixed ScriptString could be serialized with wrong length
97c12e8435 AGS: Merged Character and ObjectCache structs, and hid in draw.cpp
84a3925442 AGS: Simplified the use of get_overlay_position()
b1649597d7 AGS: Replaced Math/std Min/Max with ScummVM macros
86c363a8dd AGS: Remove ScriptOverlay.hasInternalRef flag, add actual ref
ec38c1c61c AGS: Refactor core overlay creation funcs to return ScreenOverlay*
13f40609c7 AGS: Reset currentline when exiting script function, for cc_errors
d385968209 AGS: Tidy up mobile config once more and get rid of psp_* variables
Commit: edca3fcdeae70304e46ddea2290aaa4695c3f208
https://github.com/scummvm/scummvm/commit/edca3fcdeae70304e46ddea2290aaa4695c3f208
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:05-07:00
Commit Message:
COMMON: Added move assignment operator to ScopedPtr
Changed paths:
common/ptr.h
diff --git a/common/ptr.h b/common/ptr.h
index c52667a82cc..0c509a74f2e 100644
--- a/common/ptr.h
+++ b/common/ptr.h
@@ -582,6 +582,18 @@ public:
_pointer = o;
}
+ /**
+ * Replaces the ScopedPtr with another scoped ScopedPtr.
+ */
+ template<class T2>
+ ScopedPtr &operator=(ScopedPtr<T2> &&other) {
+ PointerType oldPointer = _pointer;
+ _pointer = other._pointer;
+ other._pointer = nullptr;
+ DL()(oldPointer);
+ return *this;
+ }
+
/**
* Returns the plain pointer value.
*
Commit: 830c1b096b99f6ed5d4834a79e9acad2d5e0fa6a
https://github.com/scummvm/scummvm/commit/830c1b096b99f6ed5d4834a79e9acad2d5e0fa6a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:05-07:00
Commit Message:
AGS: introduced ObjTexture struct which combines bmp and ddb
>From upstream b628fb4d1b3ca6a85e2b2424a468f4cec94ae9c6
Also includes new implementation of std::vector class to
properly allow for arrays of smart pointers
Changed paths:
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/draw.h
engines/ags/engine/ac/game.cpp
engines/ags/engine/ac/game_state.h
engines/ags/engine/ac/global_object.cpp
engines/ags/engine/game/savegame.h
engines/ags/globals.cpp
engines/ags/globals.h
engines/ags/lib/std/utility.h
engines/ags/lib/std/vector.h
engines/ags/shared/game/main_game_file.h
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 61b0be6b489..1cdfef61680 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -79,12 +79,38 @@ namespace AGS3 {
using namespace AGS::Shared;
using namespace AGS::Engine;
+int _places_r = 3, _places_g = 2, _places_b = 3;
+
+ObjTexture::ObjTexture(ObjTexture &&o) {
+// *this = std::move(o);
+ error("TODO: ObjTexture");
+}
+
+ObjTexture::~ObjTexture() {
+ Bmp.reset();
+ if (Ddb) {
+ assert(_G(gfxDriver));
+ _G(gfxDriver)->DestroyDDB(Ddb);
+ }
+}
+
+ObjTexture &ObjTexture::operator=(ObjTexture &&o) {
+ if (Ddb) {
+ assert(_G(gfxDriver));
+ _G(gfxDriver)->DestroyDDB(Ddb);
+ }
+ Bmp = std::move(o.Bmp);
+ Ddb = o.Ddb;
+ o.Ddb = nullptr;
+ Pos = o.Pos;
+ return *this;
+}
+
+
void setpal() {
set_palette_range(_G(palette), 0, 255, 0);
}
-int _places_r = 3, _places_g = 2, _places_b = 3;
-
// PSP: convert 32 bit RGB to BGR.
Bitmap *convert_32_to_32bgr(Bitmap *tempbl) {
@@ -365,9 +391,7 @@ void init_game_drawdata() {
size_t actsps_num = _GP(game).numcharacters + MAX_ROOM_OBJECTS;
_GP(actsps).resize(actsps_num);
- _GP(actspsbmp).resize(actsps_num);
_GP(guibg).resize(_GP(game).numgui);
- _GP(guibgddb).resize(_GP(game).numgui);
size_t guio_num = 0;
// Prepare GUI cache lists and build the quick reference for controls cache
@@ -377,33 +401,20 @@ void init_game_drawdata() {
guio_num += gui.GetControlCount();
}
_GP(guiobjbg).resize(guio_num);
- _GP(guiobjddb).resize(guio_num);
- _GP(guiobjoff).resize(guio_num);
}
void dispose_game_drawdata() {
clear_drawobj_cache();
_GP(actsps).clear();
- _GP(actspsbmp).clear();
_GP(guibg).clear();
- _GP(guibgddb).clear();
-
_GP(guiobjbg).clear();
- _GP(guiobjddb).clear();
_GP(guiobjddbref).clear();
- _GP(guiobjoff).clear();
}
static void dispose_debug_room_drawdata() {
- _GP(debugRoomMaskBmp).reset();
- if (_G(debugRoomMaskDDB) != nullptr)
- _G(gfxDriver)->DestroyDDB(_G(debugRoomMaskDDB));
- _G(debugRoomMaskDDB) = nullptr;
- _GP(debugMoveListBmp).reset();
- if (_G(debugMoveListDDB) != nullptr)
- _G(gfxDriver)->DestroyDDB(_G(debugMoveListDDB));
- _G(debugMoveListDDB) = nullptr;
+ _GP(debugRoomMaskObj) = ObjTexture();
+ _GP(debugMoveListObj) = ObjTexture();
}
void dispose_room_drawdata() {
@@ -419,30 +430,13 @@ void clear_drawobj_cache() {
}
// cleanup Character + Room object textures
- for (int i = 0; i < MAX_ROOM_OBJECTS + _GP(game).numcharacters; ++i) {
- delete _GP(actsps)[i];
- _GP(actsps)[i] = nullptr;
- if (_GP(actspsbmp)[i] != nullptr)
- _G(gfxDriver)->DestroyDDB(_GP(actspsbmp)[i]);
- _GP(actspsbmp)[i] = nullptr;
- }
-
- // cleanup GUI backgrounds
- for (int i = 0; i < _GP(game).numgui; ++i) {
- delete _GP(guibg)[i];
- _GP(guibg)[i] = nullptr;
- if (_GP(guibgddb)[i])
- _G(gfxDriver)->DestroyDDB(_GP(guibgddb)[i]);
- _GP(guibgddb)[i] = nullptr;
- }
-
- for (size_t i = 0; i < _GP(guiobjbg).size(); ++i) {
- delete _GP(guiobjbg)[i];
- _GP(guiobjbg)[i] = nullptr;
- if (_GP(guiobjddb)[i])
- _G(gfxDriver)->DestroyDDB(_GP(guiobjddb)[i]);
- _GP(guiobjddb)[i] = nullptr;
- }
+ // cleanup Character + Room object textures
+ for (auto &o : _GP(actsps)) o = ObjTexture();
+ // cleanup GUI and controls textures
+ for (auto &o : _GP(guibg)) o = ObjTexture();
+ for (auto &o : _GP(guiobjbg)) o = ObjTexture();
+ // cleanup Overlay intermediate bitmaps
+ _GP(overlaybmp).clear();
dispose_debug_room_drawdata();
}
@@ -736,20 +730,22 @@ void draw_sprite_slot_support_alpha(Bitmap *ds, bool ds_has_alpha, int xpos, int
blend_mode, alpha);
}
-
-IDriverDependantBitmap *recycle_ddb_bitmap(IDriverDependantBitmap *bimp, Bitmap *source, bool hasAlpha, bool opaque) {
- if (bimp != nullptr) {
+IDriverDependantBitmap *recycle_ddb_bitmap(IDriverDependantBitmap *ddb, Bitmap *source, bool has_alpha, bool opaque) {
+ if (ddb) {
// same colour depth, width and height -> reuse
- if ((bimp->GetColorDepth() == source->GetColorDepth()) &&
- (bimp->GetWidth() == source->GetWidth()) && (bimp->GetHeight() == source->GetHeight())) {
- _G(gfxDriver)->UpdateDDBFromBitmap(bimp, source, hasAlpha);
- return bimp;
+ if ((ddb->GetColorDepth() == source->GetColorDepth()) &&
+ (ddb->GetWidth() == source->GetWidth()) && (ddb->GetHeight() == source->GetHeight())) {
+ _G(gfxDriver)->UpdateDDBFromBitmap(ddb, source, has_alpha);
+ return ddb;
}
- _G(gfxDriver)->DestroyDDB(bimp);
+ _G(gfxDriver)->DestroyDDB(ddb);
}
- bimp = _G(gfxDriver)->CreateDDBFromBitmap(source, hasAlpha, opaque);
- return bimp;
+ return _G(gfxDriver)->CreateDDBFromBitmap(source, has_alpha, opaque);
+}
+
+void sync_object_texture(ObjTexture &obj, bool has_alpha = false, bool opaque = false) {
+ obj.Ddb = recycle_ddb_bitmap(obj.Ddb, obj.Bmp.get(), has_alpha, opaque);
}
//------------------------------------------------------------------------
@@ -971,6 +967,10 @@ Bitmap *recycle_bitmap(Bitmap *bimp, int coldep, int wid, int hit, bool make_tra
return bimp;
}
+void recycle_bitmap(std::unique_ptr<Shared::Bitmap> &bimp, int coldep, int wid, int hit, bool make_transparent) {
+ bimp.reset(recycle_bitmap(bimp.release(), coldep, wid, hit, make_transparent));
+}
+
// Get the local tint at the specified X & Y co-ordinates, based on
// room regions and SetAmbientTint
// tint_amnt will be set to 0 if there is no tint enabled
@@ -1064,30 +1064,31 @@ void apply_tint_or_light(int actspsindex, int light_level,
int tint_blue, int tint_light, int coldept,
Bitmap *blitFrom) {
-// In a 256-colour game, we cannot do tinting or lightening
-// (but we can do darkening, if light_level < 0)
+ // In a 256-colour game, we cannot do tinting or lightening
+ // (but we can do darkening, if light_level < 0)
if (_GP(game).color_depth == 1) {
if ((light_level > 0) || (tint_amount != 0))
return;
}
-// we can only do tint/light if the colour depths match
- if (_GP(game).GetColorDepth() == _GP(actsps)[actspsindex]->GetColorDepth()) {
- Bitmap *oldwas;
+ auto &actsp = _GP(actsps)[actspsindex];
+ // we can only do tint/light if the colour depths match
+ if (_GP(game).GetColorDepth() == actsp.Bmp->GetColorDepth()) {
+ std::unique_ptr<Bitmap> oldwas;
// if the caller supplied a source bitmap, ->Blit from it
// (used as a speed optimisation where possible)
if (blitFrom)
- oldwas = blitFrom;
+ oldwas.reset(blitFrom);
// otherwise, make a new target bmp
else {
- oldwas = _GP(actsps)[actspsindex];
- _GP(actsps)[actspsindex] = BitmapHelper::CreateBitmap(oldwas->GetWidth(), oldwas->GetHeight(), coldept);
+ oldwas = std::move(actsp.Bmp);
+ actsp.Bmp.reset(BitmapHelper::CreateBitmap(oldwas->GetWidth(), oldwas->GetHeight(), coldept));
}
- Bitmap *active_spr = _GP(actsps)[actspsindex];
+ Bitmap *active_spr = actsp.Bmp.get();
if (tint_amount) {
// It is an RGB tint
- tint_image(active_spr, oldwas, tint_red, tint_green, tint_blue, tint_amount, tint_light);
+ tint_image(active_spr, oldwas.get(), tint_red, tint_green, tint_blue, tint_amount, tint_light);
} else {
// the RGB values passed to set_trans_blender decide whether it will darken
// or lighten sprites ( <128=darken, >128=lighten). The parameter passed
@@ -1108,26 +1109,25 @@ void apply_tint_or_light(int actspsindex, int light_level,
lit_amnt = abs(light_level) * 2;
}
- active_spr->LitBlendBlt(oldwas, 0, 0, lit_amnt);
+ active_spr->LitBlendBlt(oldwas.get(), 0, 0, lit_amnt);
}
- if (oldwas != blitFrom)
- delete oldwas;
+ if (oldwas.get() == blitFrom)
+ oldwas.release();
} else if (blitFrom) {
// sprite colour depth != game colour depth, so don't try and tint
// but we do need to do something, so copy the source
- Bitmap *active_spr = _GP(actsps)[actspsindex];
+ Bitmap *active_spr = actsp.Bmp.get();
active_spr->Blit(blitFrom, 0, 0, 0, 0, active_spr->GetWidth(), active_spr->GetHeight());
}
-
}
-Bitmap *transform_sprite(Bitmap *src, bool src_has_alpha, Bitmap *&dst, const Size dst_sz, BitmapFlip flip) {
+Bitmap *transform_sprite(Bitmap *src, bool src_has_alpha, std::unique_ptr<Bitmap> &dst, const Size dst_sz, BitmapFlip flip) {
if ((src->GetSize() == dst_sz) && (flip == kBitmap_NoFlip))
return src; // No transform: return source image
- dst = recycle_bitmap(dst, src->GetColorDepth(), dst_sz.Width, dst_sz.Height, true);
+ recycle_bitmap(dst, src->GetColorDepth(), dst_sz.Width, dst_sz.Height, true);
_G(our_eip) = 339;
// If scaled: first scale then optionally mirror
@@ -1159,7 +1159,7 @@ Bitmap *transform_sprite(Bitmap *src, bool src_has_alpha, Bitmap *&dst, const Si
// If not scaled, then simply blit mirrored
dst->FlipBlt(src, 0, 0, kBitmap_HFlip);
}
- return dst; // return transformed result
+ return dst.get(); // return transformed result
}
// Draws the specified 'sppic' sprite onto _GP(actsps)[useindx] at the
@@ -1168,9 +1168,8 @@ Bitmap *transform_sprite(Bitmap *src, bool src_has_alpha, Bitmap *&dst, const Si
// scaling or stretching was required, in which case nothing was done
static bool scale_and_flip_sprite(int useindx, int sppic, int newwidth, int newheight, bool hmirror) {
Bitmap *src = _GP(spriteset)[sppic];
- Bitmap *&dst = _GP(actsps)[useindx];
Bitmap *result = transform_sprite(src, (_GP(game).SpriteInfos[sppic].Flags & SPF_ALPHACHANNEL) != 0,
- dst, Size(newwidth, newheight), hmirror ? kBitmap_HFlip : kBitmap_NoFlip);
+ _GP(actsps)[useindx].Bmp, Size(newwidth, newheight), hmirror ? kBitmap_HFlip : kBitmap_NoFlip);
return result != src;
}
@@ -1252,11 +1251,12 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
isMirrored = true;
}
+ auto &actsp = _GP(actsps)[useindx];
if ((hardwareAccelerated) &&
- (_G(walkBehindMethod) != DrawOverCharSprite) &&
- (_G(objcache)[aa].image != nullptr) &&
- (_G(objcache)[aa].sppic == _G(objs)[aa].num) &&
- (_GP(actsps)[useindx] != nullptr)) {
+ (_G(walkBehindMethod) != DrawOverCharSprite) &&
+ (_G(objcache)[aa].image != nullptr) &&
+ (_G(objcache)[aa].sppic == _G(objs)[aa].num) &&
+ (actsp.Bmp != nullptr)) {
// HW acceleration
_G(objcache)[aa].tintamntwas = tint_level;
_G(objcache)[aa].tintredwas = tint_red;
@@ -1289,17 +1289,17 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
(_G(objcache)[aa].mirroredWas == isMirrored)) {
// the image is the same, we can use it cached!
if ((_G(walkBehindMethod) != DrawOverCharSprite) &&
- (_GP(actsps)[useindx] != nullptr))
+ (actsp.Bmp != nullptr))
return 1;
// Check if the X & Y co-ords are the same, too -- if so, there
// is scope for further optimisations
if ((_G(objcache)[aa].xwas == _G(objs)[aa].x) &&
- (_G(objcache)[aa].ywas == _G(objs)[aa].y) &&
- (_GP(actsps)[useindx] != nullptr) &&
- (_G(walk_behind_baselines_changed) == 0))
+ (_G(objcache)[aa].ywas == _G(objs)[aa].y) &&
+ (actsp.Bmp != nullptr) &&
+ (_G(walk_behind_baselines_changed) == 0))
return 1;
- _GP(actsps)[useindx] = recycle_bitmap(_GP(actsps)[useindx], coldept, sprwidth, sprheight);
- _GP(actsps)[useindx]->Blit(_G(objcache)[aa].image, 0, 0, 0, 0, _G(objcache)[aa].image->GetWidth(), _G(objcache)[aa].image->GetHeight());
+ 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());
return 0;
}
@@ -1312,7 +1312,7 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
}
if (!actspsUsed) {
// ensure actsps exists // CHECKME: why do we need this in hardware accel mode too?
- _GP(actsps)[useindx] = recycle_bitmap(_GP(actsps)[useindx], coldept, src_sprwidth, src_sprheight);
+ recycle_bitmap(actsp.Bmp, coldept, src_sprwidth, src_sprheight);
}
// direct read from source bitmap, where possible
@@ -1327,13 +1327,13 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
tint_green, tint_blue, tint_light, coldept,
comeFrom);
} else if (!actspsUsed) {
- _GP(actsps)[useindx]->Blit(_GP(spriteset)[_G(objs)[aa].num], 0, 0);
+ actsp.Bmp->Blit(_GP(spriteset)[_G(objs)[aa].num], 0, 0);
}
// Re-use the bitmap if it's the same size
_G(objcache)[aa].image = recycle_bitmap(_G(objcache)[aa].image, coldept, sprwidth, sprheight);
// Create the cached image and store it
- _G(objcache)[aa].image->Blit(_GP(actsps)[useindx], 0, 0, 0, 0, sprwidth, sprheight);
+ _G(objcache)[aa].image->Blit(actsp.Bmp.get(), 0, 0);
_G(objcache)[aa].sppic = _G(objs)[aa].num;
_G(objcache)[aa].tintamntwas = tint_level;
_G(objcache)[aa].tintredwas = tint_red;
@@ -1361,6 +1361,8 @@ void prepare_objects_for_drawing() {
int tehHeight;
int actspsIntact = construct_object_gfx(aa, nullptr, &tehHeight, false);
+ auto &actsp = _GP(actsps)[useindx];
+
// update the cache for next time
_G(objcache)[aa].xwas = _G(objs)[aa].x;
_G(objcache)[aa].ywas = _G(objs)[aa].y;
@@ -1375,37 +1377,33 @@ void prepare_objects_for_drawing() {
usebasel += _GP(thisroom).Height;
}
} else if ((!actspsIntact) && (_G(walkBehindMethod) == DrawOverCharSprite)) {
- sort_out_walk_behinds(_GP(actsps)[useindx], atxp, atyp, usebasel);
+ sort_out_walk_behinds(actsp.Bmp.get(), atxp, atyp, usebasel);
}
- if ((!actspsIntact) || (_GP(actspsbmp)[useindx] == nullptr)) {
- bool hasAlpha = (_GP(game).SpriteInfos[_G(objs)[aa].num].Flags & SPF_ALPHACHANNEL) != 0;
-
- if (_GP(actspsbmp)[useindx] != nullptr)
- _G(gfxDriver)->DestroyDDB(_GP(actspsbmp)[useindx]);
- _GP(actspsbmp)[useindx] = _G(gfxDriver)->CreateDDBFromBitmap(_GP(actsps)[useindx], hasAlpha);
+ if ((!actspsIntact) || (actsp.Ddb == nullptr)) {
+ sync_object_texture(actsp, (_GP(game).SpriteInfos[_G(objs)[aa].num].Flags & SPF_ALPHACHANNEL) != 0);
}
if (_G(gfxDriver)->HasAcceleratedTransform()) {
- _GP(actspsbmp)[useindx]->SetFlippedLeftRight(_G(objcache)[aa].mirroredWas != 0);
- _GP(actspsbmp)[useindx]->SetStretch(_G(objs)[aa].last_width, _G(objs)[aa].last_height);
- _GP(actspsbmp)[useindx]->SetTint(_G(objcache)[aa].tintredwas, _G(objcache)[aa].tintgrnwas, _G(objcache)[aa].tintbluwas, (_G(objcache)[aa].tintamntwas * 256) / 100);
+ actsp.Ddb->SetFlippedLeftRight(_G(objcache)[aa].mirroredWas != 0);
+ actsp.Ddb->SetStretch(_G(objs)[aa].last_width, _G(objs)[aa].last_height);
+ actsp.Ddb->SetTint(_G(objcache)[aa].tintredwas, _G(objcache)[aa].tintgrnwas, _G(objcache)[aa].tintbluwas, (_G(objcache)[aa].tintamntwas * 256) / 100);
if (_G(objcache)[aa].tintamntwas > 0) {
if (_G(objcache)[aa].tintlightwas == 0) // luminance of 0 -- pass 1 to enable
- _GP(actspsbmp)[useindx]->SetLightLevel(1);
+ actsp.Ddb->SetLightLevel(1);
else if (_G(objcache)[aa].tintlightwas < 250)
- _GP(actspsbmp)[useindx]->SetLightLevel(_G(objcache)[aa].tintlightwas);
+ actsp.Ddb->SetLightLevel(_G(objcache)[aa].tintlightwas);
else
- _GP(actspsbmp)[useindx]->SetLightLevel(0);
+ actsp.Ddb->SetLightLevel(0);
} else if (_G(objcache)[aa].lightlevwas != 0)
- _GP(actspsbmp)[useindx]->SetLightLevel((_G(objcache)[aa].lightlevwas * 25) / 10 + 256);
+ actsp.Ddb->SetLightLevel((_G(objcache)[aa].lightlevwas * 25) / 10 + 256);
else
- _GP(actspsbmp)[useindx]->SetLightLevel(0);
+ actsp.Ddb->SetLightLevel(0);
}
- _GP(actspsbmp)[useindx]->SetAlpha(GfxDef::LegacyTrans255ToAlpha255(_G(objs)[aa].transparent));
- add_to_sprite_list(_GP(actspsbmp)[useindx], atxp, atyp, usebasel, false);
+ actsp.Ddb->SetAlpha(GfxDef::LegacyTrans255ToAlpha255(_G(objs)[aa].transparent));
+ add_to_sprite_list(actsp.Ddb, atxp, atyp, usebasel, false);
}
}
@@ -1549,6 +1547,8 @@ void prepare_characters_for_drawing() {
_G(our_eip) = 3331;
+ auto &actsp = _GP(actsps)[useindx];
+
// if the character was the same sprite and scaling last time,
// just use the cached image
if ((_G(charcache)[aa].inUse) &&
@@ -1561,8 +1561,8 @@ void prepare_characters_for_drawing() {
(_G(charcache)[aa].tintlightwas == tint_light) &&
(_G(charcache)[aa].lightlevwas == light_level)) {
if (_G(walkBehindMethod) == DrawOverCharSprite) {
- _GP(actsps)[useindx] = recycle_bitmap(_GP(actsps)[useindx], _G(charcache)[aa].image->GetColorDepth(), _G(charcache)[aa].image->GetWidth(), _G(charcache)[aa].image->GetHeight());
- _GP(actsps)[useindx]->Blit(_G(charcache)[aa].image, 0, 0, 0, 0, _GP(actsps)[useindx]->GetWidth(), _GP(actsps)[useindx]->GetHeight());
+ recycle_bitmap(actsp.Bmp, _G(charcache)[aa].image->GetColorDepth(), _G(charcache)[aa].image->GetWidth(), _G(charcache)[aa].image->GetHeight());
+ actsp.Bmp->Blit(_G(charcache)[aa].image, 0, 0);
} else {
usingCachedImage = true;
}
@@ -1571,7 +1571,7 @@ void prepare_characters_for_drawing() {
(_G(gfxDriver)->HasAcceleratedTransform())) {
usingCachedImage = true;
} else if (_G(charcache)[aa].inUse) {
- //destroy_bitmap (charcache[aa].image);
+ //destroy_bitmap (_G(charcache)[aa].image);
_G(charcache)[aa].inUse = 0;
}
@@ -1623,7 +1623,7 @@ void prepare_characters_for_drawing() {
}
if (!actspsUsed) {
// ensure actsps exists // CHECKME: why do we need this in hardware accel mode too?
- _GP(actsps)[useindx] = recycle_bitmap(_GP(actsps)[useindx], coldept, src_sprwidth, src_sprheight);
+ recycle_bitmap(actsp.Bmp, coldept, src_sprwidth, src_sprheight);
}
_G(our_eip) = 335;
@@ -1641,14 +1641,13 @@ void prepare_characters_for_drawing() {
comeFrom);
} else if (!actspsUsed) {
// no scaling, flipping or tinting was done, so just blit it normally
- _GP(actsps)[useindx]->Blit(_GP(spriteset)[sppic], 0, 0);
+ actsp.Bmp->Blit(_GP(spriteset)[sppic], 0, 0);
}
// update the character cache with the new image
_G(charcache)[aa].inUse = 1;
- //_G(charcache)[aa].image = BitmapHelper::CreateBitmap_ (coldept, _GP(actsps)[useindx]->GetWidth(), _GP(actsps)[useindx]->GetHeight());
- _G(charcache)[aa].image = recycle_bitmap(_G(charcache)[aa].image, coldept, _GP(actsps)[useindx]->GetWidth(), _GP(actsps)[useindx]->GetHeight());
- _G(charcache)[aa].image->Blit(_GP(actsps)[useindx], 0, 0, 0, 0, _GP(actsps)[useindx]->GetWidth(), _GP(actsps)[useindx]->GetHeight());
+ _G(charcache)[aa].image = recycle_bitmap(_G(charcache)[aa].image, coldept, actsp.Bmp->GetWidth(), actsp.Bmp->GetHeight());
+ _G(charcache)[aa].image->Blit(actsp.Bmp.get(), 0, 0);
} // end if !cache.inUse
@@ -1665,31 +1664,30 @@ void prepare_characters_for_drawing() {
usebasel += _GP(thisroom).Height;
}
} else if (_G(walkBehindMethod) == DrawOverCharSprite) {
- sort_out_walk_behinds(_GP(actsps)[useindx], bgX, bgY, usebasel);
+ sort_out_walk_behinds(actsp.Bmp.get(), bgX, bgY, usebasel);
}
- if ((!usingCachedImage) || (_GP(actspsbmp)[useindx] == nullptr)) {
- bool hasAlpha = (_GP(game).SpriteInfos[sppic].Flags & SPF_ALPHACHANNEL) != 0;
-
- _GP(actspsbmp)[useindx] = recycle_ddb_bitmap(_GP(actspsbmp)[useindx], _GP(actsps)[useindx], hasAlpha);
+ if ((!usingCachedImage) || (actsp.Ddb == nullptr)) {
+ sync_object_texture(actsp, (_GP(game).SpriteInfos[sppic].Flags & SPF_ALPHACHANNEL) != 0);
}
if (_G(gfxDriver)->HasAcceleratedTransform()) {
- _GP(actspsbmp)[useindx]->SetStretch(newwidth, newheight);
- _GP(actspsbmp)[useindx]->SetFlippedLeftRight(isMirrored);
- _GP(actspsbmp)[useindx]->SetTint(tint_red, tint_green, tint_blue, (tint_amount * 256) / 100);
+ actsp.Ddb->SetStretch(newwidth, newheight);
+ actsp.Ddb->SetFlippedLeftRight(isMirrored);
+ actsp.Ddb->SetTint(tint_red, tint_green, tint_blue, (tint_amount * 256) / 100);
if (tint_amount != 0) {
if (tint_light == 0) // tint with 0 luminance, pass as 1 instead
- _GP(actspsbmp)[useindx]->SetLightLevel(1);
+ actsp.Ddb->SetLightLevel(1);
else if (tint_light < 250)
- _GP(actspsbmp)[useindx]->SetLightLevel(tint_light);
+ actsp.Ddb->SetLightLevel(tint_light);
else
- _GP(actspsbmp)[useindx]->SetLightLevel(0);
+ actsp.Ddb->SetLightLevel(0);
} else if (light_level != 0)
- _GP(actspsbmp)[useindx]->SetLightLevel((light_level * 25) / 10 + 256);
+ actsp.Ddb->SetLightLevel((light_level * 25) / 10 + 256);
else
- _GP(actspsbmp)[useindx]->SetLightLevel(0);
+ actsp.Ddb->SetLightLevel(0);
+
}
_G(our_eip) = 337;
@@ -1697,19 +1695,20 @@ void prepare_characters_for_drawing() {
chin->actx = atxp;
chin->acty = atyp;
- _GP(actspsbmp)[useindx]->SetAlpha(GfxDef::LegacyTrans255ToAlpha255(chin->transparency));
- add_to_sprite_list(_GP(actspsbmp)[useindx], bgX, bgY, usebasel, false);
+ actsp.Ddb->SetAlpha(GfxDef::LegacyTrans255ToAlpha255(chin->transparency));
+ add_to_sprite_list(actsp.Ddb, bgX, bgY, usebasel, false);
}
}
-Shared::Bitmap *get_cached_character_image(int charid) {
- return _GP(actsps)[charid + MAX_ROOM_OBJECTS];
+Bitmap *get_cached_character_image(int charid) {
+ return _GP(actsps)[charid + MAX_ROOM_OBJECTS].Bmp.get();
}
-Shared::Bitmap *get_cached_object_image(int objid) {
- return _GP(actsps)[objid];
+Bitmap *get_cached_object_image(int objid) {
+ return _GP(actsps)[objid].Bmp.get();
}
+
// Compiles a list of room sprites (characters, objects, background)
void prepare_room_sprites() {
// Background sprite is required for the non-software renderers always,
@@ -1760,10 +1759,10 @@ void prepare_room_sprites() {
// Debug room overlay
update_room_debug();
- if ((_G(debugRoomMask) != kRoomAreaNone) && _G(debugRoomMaskDDB))
- add_thing_to_draw(_G(debugRoomMaskDDB), 0, 0);
- if ((_G(debugMoveListChar) >= 0) && _G(debugMoveListDDB))
- add_thing_to_draw(_G(debugMoveListDDB), 0, 0);
+ if ((_G(debugRoomMask) != kRoomAreaNone) && _GP(debugRoomMaskObj).Ddb)
+ add_thing_to_draw(_GP(debugRoomMaskObj).Ddb, 0, 0);
+ if ((_G(debugMoveListChar) >= 0) && _GP(debugMoveListObj).Ddb)
+ add_thing_to_draw(_GP(debugMoveListObj).Ddb, 0, 0);
}
// Draws the black surface behind (or rather between) the room viewports
@@ -1869,15 +1868,13 @@ void draw_gui_controls(GUIMain &gui) {
if (!obj->HasChanged())
continue;
- auto *&objbg_bmp = _GP(guiobjbg)[draw_index];
- auto *&objbg_ddb = _GP(guiobjddb)[draw_index];
+ auto &objbg = _GP(guiobjbg)[draw_index];
Rect obj_surf = obj->CalcGraphicRect(GUI::Options.ClipControls);
- objbg_bmp = recycle_bitmap(objbg_bmp, _GP(game).GetColorDepth(), obj_surf.GetWidth(), obj_surf.GetHeight());
- objbg_bmp->ClearTransparent();
- obj->Draw(objbg_bmp, obj->X - obj_surf.Left, obj->Y - obj_surf.Top);
+ recycle_bitmap(objbg.Bmp, _GP(game).GetColorDepth(), obj_surf.GetWidth(), obj_surf.GetHeight(), true);
+ obj->Draw(objbg.Bmp.get(), obj->X - obj_surf.Left, obj->Y - obj_surf.Top);
- objbg_ddb = recycle_ddb_bitmap(objbg_ddb, objbg_bmp, obj->HasAlphaChannel());
- _GP(guiobjoff)[draw_index] = Point(obj_surf.GetLT());
+ sync_object_texture(objbg, obj->HasAlphaChannel());
+ objbg.Pos = Point(obj_surf.GetLT());
obj->ClearChanged();
}
}
@@ -1937,29 +1934,27 @@ void draw_gui_and_overlays() {
if (!gui.HasChanged() && !gui.HasControlsChanged()) continue; // no changes: no need to update image
if (gui.Transparency == 255) continue; // 100% transparent
- auto *&guibg_bmp = _GP(guibg)[index];
- auto *&guibg_ddb = _GP(guibgddb)[index];
- guibg_bmp = recycle_bitmap(guibg_bmp, _GP(game).GetColorDepth(), gui.Width, gui.Height);
-
_G(eip_guinum) = index;
_G(our_eip) = 372;
const bool draw_with_controls = !draw_controls_as_textures;
if (gui.HasChanged() || (draw_with_controls && gui.HasControlsChanged())) {
- guibg_bmp->ClearTransparent();
- if (draw_with_controls)
- gui.DrawWithControls(guibg_bmp);
- else
- gui.DrawSelf(guibg_bmp);
-
- const bool is_alpha = gui.HasAlphaChannel();
- if (is_alpha) {
- if ((_GP(game).options[OPT_NEWGUIALPHA] == kGuiAlphaRender_Legacy) && (gui.BgImage > 0)) {
- // old-style (pre-3.0.2) GUI alpha rendering
- repair_alpha_channel(guibg_bmp, _GP(spriteset)[gui.BgImage]);
- }
- }
-
- guibg_ddb = recycle_ddb_bitmap(guibg_ddb, guibg_bmp, is_alpha);
+ auto &gbg = _GP(guibg)[index];
+ recycle_bitmap(gbg.Bmp, _GP(game).GetColorDepth(), gui.Width, gui.Height, true);
+ if (draw_with_controls)
+ gui.DrawWithControls(gbg.Bmp.get());
+ else
+ gui.DrawSelf(gbg.Bmp.get());
+
+ const bool is_alpha = gui.HasAlphaChannel();
+ if (is_alpha)
+ {
+ if ((_GP(game).options[OPT_NEWGUIALPHA] == kGuiAlphaRender_Legacy) && (gui.BgImage > 0))
+ {
+ // old-style (pre-3.0.2) GUI alpha rendering
+ repair_alpha_channel(gbg.Bmp.get(), _GP(spriteset)[gui.BgImage]);
+ }
+ }
+ sync_object_texture(gbg, is_alpha);
}
_G(our_eip) = 373;
@@ -1984,7 +1979,7 @@ void draw_gui_and_overlays() {
(gui.PopupStyle != kGUIPopupNoAutoRemove))
continue;
- auto *gui_ddb = _GP(guibgddb)[index];
+ auto *gui_ddb = _GP(guibg)[index].Ddb;
assert(gui_ddb); // Test for missing texture, might happen if not marked for update
if (!gui_ddb) continue;
gui_ddb->SetAlpha(GfxDef::LegacyTrans255ToAlpha255(gui.Transparency));
@@ -2031,13 +2026,13 @@ void draw_gui_and_overlays() {
(obj->Width <= 0 || obj->Height <= 0) ||
(!obj->IsEnabled() && (GUI::Options.DisabledStyle == kGuiDis_Blackout)))
continue;
- auto *obj_ddb = _GP(guiobjddb)[draw_index + obj_id];
+ auto *obj_ddb = _GP(guiobjbg)[draw_index + obj_id].Ddb;
assert(obj_ddb); // Test for missing texture, might happen if not marked for update
if (!obj_ddb) continue;
obj_ddb->SetAlpha(GfxDef::LegacyTrans255ToAlpha255(obj->GetTransparency()));
_G(gfxDriver)->DrawSprite(
- _GP(guiobjoff)[draw_index + obj_id].X,
- _GP(guiobjoff)[draw_index + obj_id].Y,
+ _GP(guiobjbg)[draw_index + obj_id].Pos.X,
+ _GP(guiobjbg)[draw_index + obj_id].Pos.Y,
obj_ddb);
}
_G(gfxDriver)->EndSpriteBatch();
@@ -2308,15 +2303,15 @@ void debug_draw_room_mask(RoomAreaMask mask) {
if (!_G(gfxDriver)->HasAcceleratedTransform() &&
(mask != kRoomAreaWalkBehind) &&
(bmp->GetSize() != Size(_GP(thisroom).Width, _GP(thisroom).Height))) {
- _GP(debugRoomMaskBmp).reset(recycle_bitmap(_GP(debugRoomMaskBmp).release(),
- bmp->GetColorDepth(), _GP(thisroom).Width, _GP(thisroom).Height));
- _GP(debugRoomMaskBmp)->StretchBlt(bmp, RectWH(0, 0, _GP(thisroom).Width, _GP(thisroom).Height));
- bmp = _GP(debugRoomMaskBmp).get();
+ recycle_bitmap(_GP(debugRoomMaskObj).Bmp,
+ bmp->GetColorDepth(), _GP(thisroom).Width, _GP(thisroom).Height);
+ _GP(debugRoomMaskObj).Bmp->StretchBlt(bmp, RectWH(0, 0, _GP(thisroom).Width, _GP(thisroom).Height));
+ bmp = _GP(debugRoomMaskObj).Bmp.get();
}
- _G(debugRoomMaskDDB) = recycle_ddb_bitmap(_G(debugRoomMaskDDB), bmp, false, true);
- _G(debugRoomMaskDDB)->SetAlpha(150);
- _G(debugRoomMaskDDB)->SetStretch(_GP(thisroom).Width, _GP(thisroom).Height);
+ _GP(debugRoomMaskObj).Ddb = recycle_ddb_bitmap(_GP(debugRoomMaskObj).Ddb, bmp, false, true);
+ _GP(debugRoomMaskObj).Ddb->SetAlpha(150);
+ _GP(debugRoomMaskObj).Ddb->SetStretch(_GP(thisroom).Width, _GP(thisroom).Height);
}
void debug_draw_movelist(int charnum) {
@@ -2328,23 +2323,23 @@ void update_room_debug() {
Bitmap *bmp = prepare_walkable_areas(-1);
// Software mode scaling
if (!_G(gfxDriver)->HasAcceleratedTransform() && (_GP(thisroom).MaskResolution > 1)) {
- _GP(debugRoomMaskBmp).reset(recycle_bitmap(_GP(debugRoomMaskBmp).release(),
- bmp->GetColorDepth(), _GP(thisroom).Width, _GP(thisroom).Height));
- _GP(debugRoomMaskBmp)->StretchBlt(bmp, RectWH(0, 0, _GP(thisroom).Width, _GP(thisroom).Height));
- bmp = _GP(debugRoomMaskBmp).get();
+ recycle_bitmap(_GP(debugRoomMaskObj).Bmp,
+ bmp->GetColorDepth(), _GP(thisroom).Width, _GP(thisroom).Height);
+ _GP(debugRoomMaskObj).Bmp->StretchBlt(bmp, RectWH(0, 0, _GP(thisroom).Width, _GP(thisroom).Height));
+ bmp = _GP(debugRoomMaskObj).Bmp.get();
}
- _G(debugRoomMaskDDB) = recycle_ddb_bitmap(_G(debugRoomMaskDDB), bmp, false, true);
- _G(debugRoomMaskDDB)->SetAlpha(150);
- _G(debugRoomMaskDDB)->SetStretch(_GP(thisroom).Width, _GP(thisroom).Height);
+ _GP(debugRoomMaskObj).Ddb = recycle_ddb_bitmap(_GP(debugRoomMaskObj).Ddb, bmp, false, true);
+ _GP(debugRoomMaskObj).Ddb->SetAlpha(150);
+ _GP(debugRoomMaskObj).Ddb->SetStretch(_GP(thisroom).Width, _GP(thisroom).Height);
}
if (_G(debugMoveListChar) >= 0) {
const int mult = _G(gfxDriver)->HasAcceleratedTransform() ? _GP(thisroom).MaskResolution : 1;
if (_G(gfxDriver)->HasAcceleratedTransform())
- _GP(debugMoveListBmp).reset(recycle_bitmap(_GP(debugMoveListBmp).release(), _GP(game).GetColorDepth(),
- _GP(thisroom).WalkAreaMask->GetWidth(), _GP(thisroom).WalkAreaMask->GetHeight(), true));
+ recycle_bitmap(_GP(debugMoveListObj).Bmp, _GP(game).GetColorDepth(),
+ _GP(thisroom).WalkAreaMask->GetWidth(), _GP(thisroom).WalkAreaMask->GetHeight(), true);
else
- _GP(debugMoveListBmp).reset(recycle_bitmap(_GP(debugMoveListBmp).release(), _GP(game).GetColorDepth(),
- _GP(thisroom).Width, _GP(thisroom).Height, true));
+ recycle_bitmap(_GP(debugMoveListObj).Bmp, _GP(game).GetColorDepth(),
+ _GP(thisroom).Width, _GP(thisroom).Height, true);
if (_GP(game).chars[_G(debugMoveListChar)].walking > 0) {
int mlsnum = _GP(game).chars[_G(debugMoveListChar)].walking;
@@ -2356,13 +2351,13 @@ void update_room_debug() {
short srcy = short(cmls.pos[i] & 0x00ffff);
short targetx = short((cmls.pos[i + 1] >> 16) & 0x00ffff);
short targety = short(cmls.pos[i + 1] & 0x00ffff);
- _GP(debugMoveListBmp)->DrawLine(Line(srcx / mult, srcy / mult, targetx / mult, targety / mult),
+ _GP(debugMoveListObj).Bmp->DrawLine(Line(srcx / mult, srcy / mult, targetx / mult, targety / mult),
MakeColor(i + 1));
}
}
- _G(debugMoveListDDB) = recycle_ddb_bitmap(_G(debugMoveListDDB), _GP(debugMoveListBmp).get(), false, false);
- _G(debugRoomMaskDDB)->SetAlpha(150);
- _G(debugMoveListDDB)->SetStretch(_GP(thisroom).Width, _GP(thisroom).Height);
+ sync_object_texture(_GP(debugMoveListObj));
+ _GP(debugMoveListObj).Ddb->SetAlpha(150);
+ _GP(debugMoveListObj).Ddb->SetStretch(_GP(thisroom).Width, _GP(thisroom).Height);
}
}
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index fb1648a841b..4ec6e5599a7 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -26,6 +26,7 @@
#include "ags/shared/core/types.h"
#include "ags/shared/ac/common_defines.h"
#include "ags/shared/gfx/gfx_def.h"
+#include "ags/shared/gfx/allegro_bitmap.h"
#include "ags/shared/gfx/bitmap.h"
#include "ags/shared/game/room_struct.h"
@@ -59,6 +60,28 @@ struct RoomCameraDrawData {
bool IsOverlap; // whether room viewport overlaps any others (marking dirty rects is complicated)
};
+// ObjTexture is a helper struct that pairs a raw bitmap with
+// a renderer's texture and an optional position
+struct ObjTexture {
+ // Raw bitmap
+ std::unique_ptr<Shared::Bitmap> Bmp;
+ // Corresponding texture, created by renderer
+ Engine::IDriverDependantBitmap *Ddb = nullptr;
+ // Sprite's position, may be used in case the texture's pos is different
+ // from the object's logical position (x,y,w,h) for some reason.
+ Point Pos;
+
+ ObjTexture() = default;
+ ObjTexture(Shared::Bitmap *bmp, Engine::IDriverDependantBitmap *ddb, int x, int y)
+ : Bmp(bmp), Ddb(ddb), Pos(x, y) {
+ }
+ ObjTexture(const ObjTexture &) = default;
+ ObjTexture(ObjTexture &&o);
+ ~ObjTexture();
+
+ ObjTexture &operator =(ObjTexture &&o);
+};
+
// Converts AGS color index to the actual bitmap color using game's color depth
int MakeColor(int color_index);
@@ -108,7 +131,8 @@ void mark_current_background_dirty();
// Avoid freeing and reallocating the memory if possible
Shared::Bitmap *recycle_bitmap(Shared::Bitmap *bimp, int coldep, int wid, int hit, bool make_transparent = false);
-Engine::IDriverDependantBitmap *recycle_ddb_bitmap(Engine::IDriverDependantBitmap *bimp, Shared::Bitmap *source, bool hasAlpha = false, bool opaque = false);
+void recycle_bitmap(std::unique_ptr<Shared::Bitmap> &bimp, int coldep, int wid, int hit, bool make_transparent = false);
+Engine::IDriverDependantBitmap *recycle_ddb_bitmap(Engine::IDriverDependantBitmap *ddb, Shared::Bitmap *source, bool has_alpha = false, bool opaque = false);
// Draw everything
void render_graphics(Engine::IDriverDependantBitmap *extraBitmap = nullptr, int extraX = 0, int extraY = 0);
// Construct game scene, scheduling drawing list for the renderer
@@ -137,7 +161,7 @@ void draw_gui_sprite(Shared::Bitmap *ds, bool use_alpha, int xpos, int ypos,
// 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, Shared::Bitmap *&dst,
+Shared::Bitmap *transform_sprite(Shared::Bitmap *src, bool src_has_alpha, std::unique_ptr<Shared::Bitmap> &dst,
const Size dst_sz, Shared::BitmapFlip flip = Shared::kBitmap_NoFlip);
// Render game on screen
void render_to_screen();
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 25e1b264d15..11b27cf73f3 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -882,14 +882,11 @@ void save_game(int slotn, const char *descript) {
VALIDATE_STRING(descript);
String nametouse = get_save_game_path(slotn);
- UBitmap screenShot;
-
- // WORKAROUND: AGS originally only creates savegames if the game flags
- // that it supports it. But we want it all the time for ScummVM GMM
- if (/*_GP(game).options[OPT_SAVESCREENSHOT] != 0*/ true)
+ std::unique_ptr<Bitmap> screenShot;
+ if (_GP(game).options[OPT_SAVESCREENSHOT] != 0)
screenShot.reset(create_savegame_screenshot());
- Engine::UStream out(StartSavegame(nametouse, descript, screenShot.get()));
+ std::unique_ptr<Stream> out(StartSavegame(nametouse, descript, screenShot.get()));
if (out == nullptr) {
Display("ERROR: Unable to open savegame file for writing!");
return;
diff --git a/engines/ags/engine/ac/game_state.h b/engines/ags/engine/ac/game_state.h
index 7f31420a9be..f087b92707e 100644
--- a/engines/ags/engine/ac/game_state.h
+++ b/engines/ags/engine/ac/game_state.h
@@ -227,7 +227,7 @@ struct GameState {
short temporarily_turned_off_character = 0; // Hide Player Charactr ticked
short inv_backwards_compatibility = 0;
std::vector<int> gui_draw_order; // used only for hit detection now
- std::vector<AGS::Shared::String> do_once_tokens = 0;
+ std::vector<AGS::Shared::String> do_once_tokens;
int text_min_display_time_ms = 0;
int ignore_user_input_after_text_timeout_ms = 0;
int32_t default_audio_type_volumes[MAX_AUDIO_TYPES];
diff --git a/engines/ags/engine/ac/global_object.cpp b/engines/ags/engine/ac/global_object.cpp
index 05ec64bc1a5..37091da362f 100644
--- a/engines/ags/engine/ac/global_object.cpp
+++ b/engines/ags/engine/ac/global_object.cpp
@@ -521,12 +521,12 @@ void GetObjectPropertyText(int item, const char *property, char *bufer) {
Bitmap *GetObjectImage(int obj, int *isFlipped) {
if (!_G(gfxDriver)->HasAcceleratedTransform()) {
- if (_GP(actsps)[obj] != nullptr) {
- // the actsps image is pre-flipped, so no longer register the image as such
+ Bitmap *actsp = get_cached_object_image(obj);
+ if (actsp) {
+ // the cached image is pre-flipped, so no longer register the image as such
if (isFlipped)
*isFlipped = 0;
-
- return _GP(actsps)[obj];
+ return actsp;
}
}
return _GP(spriteset)[_G(objs)[obj].num];
diff --git a/engines/ags/engine/game/savegame.h b/engines/ags/engine/game/savegame.h
index 9d6d9587f68..47b76788a31 100644
--- a/engines/ags/engine/game/savegame.h
+++ b/engines/ags/engine/game/savegame.h
@@ -97,13 +97,6 @@ String GetSavegameErrorText(SavegameErrorType err);
typedef TypedCodeError<SavegameErrorType, GetSavegameErrorText> SavegameError;
typedef ErrorHandle<SavegameError> HSaveError;
-typedef std::unique_ptr<Bitmap> UBitmap;
-#ifdef UNUSED_AGS_PLATFORM_SCUMMVM
-typedef std::shared_ptr<Stream> UStream;
-#else
-typedef std::unique_ptr<Stream> UStream;
-#endif
-
// SavegameSource defines a successfully opened savegame stream
struct SavegameSource {
@@ -117,7 +110,7 @@ struct SavegameSource {
// Savegame format version
SavegameVersion Version;
// A ponter to the opened stream
- UStream InputStream;
+ std::unique_ptr<Stream> InputStream;
SavegameSource();
};
@@ -156,7 +149,7 @@ struct SavegameDescription {
int ColorDepth;
String UserText;
- UBitmap UserImage;
+ std::unique_ptr<Bitmap> UserImage;
SavegameDescription();
};
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 4f15ea49e56..fbe3dd24b00 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -173,23 +173,22 @@ Globals::Globals() {
Common::fill(_dynamicallyCreatedSurfaces, _dynamicallyCreatedSurfaces +
MAX_DYNAMIC_SURFACES, (AGS::Shared::Bitmap *)nullptr);
- _actsps = new std::vector<Shared::Bitmap *>();
- _actspsbmp = new std::vector<Engine::IDriverDependantBitmap *>();
- _guibg = new std::vector<Shared::Bitmap *>();
- _guibgddb = new std::vector<Engine::IDriverDependantBitmap *>();
- _debugRoomMaskBmp = new std::unique_ptr<Shared::Bitmap>();
- _debugMoveListBmp = new std::unique_ptr<Shared::Bitmap>();
+ _actsps = new std::vector<ObjTexture>();
+ _guibg = new std::vector<ObjTexture>();
+ _guiobjbg = new std::vector<ObjTexture>();
+
+ _guiobjddb = new std::vector<Engine::IDriverDependantBitmap *>();
+ _guiobjoff = new std::vector<Point>();
+ _guiobjddbref = new std::vector<int>();
+ _overlaybmp = new std::vector<std::unique_ptr<Shared::Bitmap> >();
+ _debugRoomMaskObj = new ObjTexture();
+ _debugMoveListObj = new ObjTexture();
_maincoltable = new COLOR_MAP();
_palette = new color[256];
for (int i = 0; i < PALETTE_COUNT; ++i)
_palette[i].clear();
- _guiobjbg = new std::vector<Shared::Bitmap *>();
- _guiobjddb = new std::vector<Engine::IDriverDependantBitmap *>();
- _guiobjoff = new std::vector<Point>();
- _guiobjddbref = new std::vector<int>();
- _overlaybmp = new std::vector<Shared::Bitmap *>();
// draw_software.cpp globals
_BlackRects = new DirtyRects();
@@ -429,19 +428,18 @@ Globals::~Globals() {
delete _sprlist;
delete _thingsToDrawList;
delete _actsps;
- delete _actspsbmp;
delete _guibg;
- delete _guibgddb;
- delete _debugRoomMaskBmp;
- delete _debugMoveListBmp;
- delete[] _dynamicallyCreatedSurfaces;
- delete[] _palette;
- delete _maincoltable;
delete _guiobjbg;
+ delete _guiobjddbref;
delete _guiobjddb;
delete _guiobjoff;
- delete _guiobjddbref;
delete _overlaybmp;
+ delete _debugRoomMaskObj;
+ delete _debugMoveListObj;
+
+ delete[] _dynamicallyCreatedSurfaces;
+ delete[] _palette;
+ delete _maincoltable;
// draw_software.cpp globals
delete _BlackRects;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index a34069c72dd..52aa0442ffb 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -578,19 +578,20 @@ public:
// actsps is used for temporary storage of the bitamp image
// of the latest version of the sprite
- std::vector<Shared::Bitmap *> *_actsps;
- std::vector<Engine::IDriverDependantBitmap *> *_actspsbmp;
- // temporary cache of walk-behind for this actsps image
+ std::vector<ObjTexture> *_actsps;
// GUI surfaces
- std::vector<Shared::Bitmap *> *_guibg;
- std::vector<Engine::IDriverDependantBitmap *> *_guibgddb;
+ std::vector<ObjTexture> *_guibg;
+ // GUI control surfaces
+ std::vector<ObjTexture> *_guiobjbg;
+ // first control texture index of each GUI
+ std::vector<int> *_guiobjddbref;
+ // Overlay's cached transformed bitmap, for software mode
+ std::vector<std::unique_ptr<Shared::Bitmap> > *_overlaybmp;
// For debugging room masks
+ ObjTexture *_debugRoomMaskObj;
+ ObjTexture *_debugMoveListObj;
RoomAreaMask _debugRoomMask = kRoomAreaNone;
- std::unique_ptr<Shared::Bitmap> *_debugRoomMaskBmp;
- Engine::IDriverDependantBitmap *_debugRoomMaskDDB = nullptr;
int _debugMoveListChar = -1;
- std::unique_ptr<Shared::Bitmap> *_debugMoveListBmp;
- Engine::IDriverDependantBitmap *_debugMoveListDDB = nullptr;
bool _current_background_is_dirty = false;
// Room background sprite
@@ -604,13 +605,8 @@ public:
color *_palette;
COLOR_MAP *_maincoltable;
- // GUI control surfaces
- std::vector<Shared::Bitmap *> *_guiobjbg;
std::vector<Engine::IDriverDependantBitmap *> *_guiobjddb;
std::vector<Point> *_guiobjoff; // because surface may be larger than logical position
- std::vector<int> *_guiobjddbref; // first control texture index of each GUI
- // Overlay's cached transformed bitmap, for software mode
- std::vector<Shared::Bitmap *> *_overlaybmp;
/**@}*/
diff --git a/engines/ags/lib/std/utility.h b/engines/ags/lib/std/utility.h
index d701a3c3dd5..d50acfa85c6 100644
--- a/engines/ags/lib/std/utility.h
+++ b/engines/ags/lib/std/utility.h
@@ -46,7 +46,17 @@ pair<T1, T2> make_pair(T1 first, T2 second) {
// STRUCT TEMPLATE remove_reference
template <class _Ty>
struct remove_reference {
- using type = _Ty;
+ typedef _Ty type;
+};
+
+template<class _Ty>
+struct remove_reference<_Ty &> {
+ typedef _Ty type;
+};
+
+template<class _Ty>
+struct remove_reference<_Ty &&> {
+ typedef _Ty type;
};
template <class _Ty>
diff --git a/engines/ags/lib/std/vector.h b/engines/ags/lib/std/vector.h
index 06e93f800e8..340a7b06138 100644
--- a/engines/ags/lib/std/vector.h
+++ b/engines/ags/lib/std/vector.h
@@ -22,13 +22,40 @@
#ifndef AGS_STD_VECTOR_H
#define AGS_STD_VECTOR_H
-#include "common/array.h"
+#include "ags/lib/std/utility.h"
+#include "common/scummsys.h"
+#include "common/algorithm.h"
+#include "common/memory.h"
+#include "common/initializer_list.h"
namespace AGS3 {
namespace std {
+template<class In, class Type>
+Type *uninitialized_move(In first, In last, Type *dst) {
+ while (first != last) {
+ Type &t = *new ((void *)dst++) Type();
+ t = std::move(*first++);
+ }
+
+ return dst;
+}
+
template<class T>
-class vector : public Common::Array<T> {
+class vector {
+public:
+ typedef T *iterator; /*!< vector iterator. */
+ typedef const T *const_iterator; /*!< Const-qualified array iterator. */
+
+ typedef T value_type; /*!< Value type of the array. */
+
+ typedef uint size_type; /*!< Size type of the array. */
+
+protected:
+ size_type _capacity; /*!< Maximum number of elements the array can hold. */
+ size_type _size; /*!< How many elements the array holds. */
+ T *_storage; /*!< Memory used for element storage. */
+
public:
struct reverse_iterator {
private:
@@ -86,28 +113,256 @@ public:
return _index > rhs._index;
}
};
-
- using iterator = typename Common::Array<T>::iterator;
- using const_iterator = typename Common::Array<T>::const_iterator;
public:
- typedef T reference;
- typedef const T const_reference;
+ vector() : _capacity(0), _size(0), _storage(nullptr) {
+ }
- vector() : Common::Array<T>() {
+ /**
+ * Construct an array with @p count default-inserted instances of @p T. No
+ * copies are made.
+ */
+ explicit vector(size_type count) : _size(count) {
+ allocCapacity(count);
+ for (size_type i = 0; i < count; ++i)
+ new ((void *)&_storage[i]) T();
}
- vector(size_t newSize) : Common::Array<T>() {
- Common::Array<T>::resize(newSize);
+
+ /**
+ * Construct an array with @p count copies of elements with value @p value.
+ */
+ vector(size_type count, const T &value) : _size(count) {
+ allocCapacity(count);
+ Common::uninitialized_fill_n(_storage, count, value);
}
- vector(size_t newSize, const T elem) {
- resize(newSize, elem);
+
+ /**
+ * Construct an array as a copy of the given @p array.
+ */
+ vector(const vector<T> &array) : _capacity(array._size), _size(array._size), _storage(nullptr) {
+ if (array._storage) {
+ allocCapacity(_size);
+ Common::uninitialized_copy(array._storage, array._storage + _size, _storage);
+ }
}
+ /**
+ * Construct an array as a copy of the given array using the C++11 move semantic.
+ */
+ vector(vector<T> &&old) : _capacity(old._capacity), _size(old._size), _storage(old._storage) {
+ old._storage = nullptr;
+ old._capacity = 0;
+ old._size = 0;
+ }
+
+ /**
+ * Construct an array using list initialization.
+ * For example:
+ * @code
+ * Common::vector<int> myArray = {1, 7, 42};
+ * @endcode
+ * constructs an array with 3 elements whose values are 1, 7, and 42 respectively.
+ * @note
+ * This constructor is only available when C++11 support is enabled.
+ */
+ vector(::std::initializer_list<T> list) : _size(list.size()) {
+ allocCapacity(list.size());
+ if (_storage)
+ Common::uninitialized_copy(list.begin(), list.end(), _storage);
+ }
+
+ /**
+ * Construct an array by copying data from a regular array.
+ */
+ template<class T2>
+ vector(const T2 *array, size_type n) {
+ _size = n;
+ allocCapacity(n);
+ Common::uninitialized_copy(array, array + _size, _storage);
+ }
+
+ ~vector() {
+ freeStorage(_storage, _size);
+ _storage = nullptr;
+ _capacity = _size = 0;
+ }
+
+ /** Append an element to the end of the array. */
+ void push_back(const T &element) {
+ if (_size + 1 <= _capacity)
+ new ((void *)&_storage[_size++]) T(element);
+ else
+ insert_aux(end(), &element, &element + 1);
+ }
+
+ /** Append an element to the end of the array. */
+ void push_back(const vector<T> &array) {
+ if (_size + array.size() <= _capacity) {
+ Common::uninitialized_copy(array.begin(), array.end(), end());
+ _size += array.size();
+ } else
+ insert_aux(end(), array.begin(), array.end());
+ }
+
+ void insert(const T &element) {
+ this->push_back(element);
+ }
+
+ /**
+ * Adds a range of items at the specified position in the array
+ */
+ void insert(iterator position, const_iterator first, const_iterator last) {
+ int destIndex = position - this->begin();
+ for (; first != last; ++first) {
+ insert_at(destIndex++, *first);
+ }
+ }
+
+ /** Remove the last element of the array. */
+ void pop_back() {
+ assert(_size > 0);
+ _size--;
+ // We also need to destroy the last object properly here.
+ _storage[_size].~T();
+ }
+
+ /** Return a pointer to the underlying memory serving as element storage. */
+ const T *data() const {
+ return _storage;
+ }
+
+ /** Return a pointer to the underlying memory serving as element storage. */
+ T *data() {
+ return _storage;
+ }
+
+ /** Return a reference to the first element of the array. */
+ T &front() {
+ assert(_size > 0);
+ return _storage[0];
+ }
+
+ /** Return a reference to the first element of the array. */
+ const T &front() const {
+ assert(_size > 0);
+ return _storage[0];
+ }
+
+ /** Return a reference to the last element of the array. */
+ T &back() {
+ assert(_size > 0);
+ return _storage[_size - 1];
+ }
+
+ /** Return a reference to the last element of the array. */
+ const T &back() const {
+ assert(_size > 0);
+ return _storage[_size - 1];
+ }
+
+ /** Insert an element into the array at the given position. */
+ void insert_at(size_type idx, const T &element) {
+ assert(idx <= _size);
+ insert_aux(_storage + idx, &element, &element + 1);
+ }
+
+ /** Insert copies of all the elements from the given array into this array at the given position. */
+ void insert_at(size_type idx, const vector<T> &array) {
+ assert(idx <= _size);
+ insert_aux(_storage + idx, array.begin(), array.end());
+ }
+
+ /**
+ * Insert an element before @p pos.
+ */
+ void insert(iterator pos, const T &element) {
+ insert_aux(pos, &element, &element + 1);
+ }
+
+ /** Remove an element at the given position from the array and return the value of that element. */
+ T remove_at(size_type idx) {
+ assert(idx < _size);
+ T tmp = _storage[idx];
+ Common::copy(_storage + idx + 1, _storage + _size, _storage + idx);
+ _size--;
+ // We also need to destroy the last object properly here.
+ _storage[_size].~T();
+ return tmp;
+ }
+
+ // TODO: insert, remove, ...
+
+ T &at(size_t index) {
+ return (*this)[index];
+ }
+ const T &at(size_t index) const {
+ return (*this)[index];
+ }
+
+ /** Return a reference to the element at the given position in the array. */
+ T &operator[](size_type idx) {
+ assert(idx < _size);
+ return _storage[idx];
+ }
+
+ /** Return a const reference to the element at the given position in the array. */
+ const T &operator[](size_type idx) const {
+ assert(idx < _size);
+ return _storage[idx];
+ }
+
+ /** Assign the given @p array to this array. */
+ vector<T> &operator=(const vector<T> &array) {
+ if (this == &array)
+ return *this;
+
+ freeStorage(_storage, _size);
+ _size = array._size;
+ allocCapacity(_size);
+ Common::uninitialized_copy(array._storage, array._storage + _size, _storage);
+
+ return *this;
+ }
+
+ /** Assign the given array to this array using the C++11 move semantic. */
+ vector &operator=(vector<T> &&old) {
+ if (this == &old)
+ return *this;
+
+ freeStorage(_storage, _size);
+ _capacity = old._capacity;
+ _size = old._size;
+ _storage = old._storage;
+
+ old._storage = nullptr;
+ old._capacity = 0;
+ old._size = 0;
+
+ return *this;
+ }
+
+ /** Return the size of the array. */
+ size_type size() const {
+ return _size;
+ }
+
+ /** Clear the array of all its elements. */
+ void clear() {
+ freeStorage(_storage, _size);
+ _storage = nullptr;
+ _size = 0;
+ _capacity = 0;
+ }
+
+ /** Erase the element at @p pos position and return an iterator pointing to the next element in the array. */
iterator erase(iterator pos) {
- return Common::Array<T>::erase(pos);
+ Common::copy(pos + 1, _storage + _size, pos);
+ _size--;
+ // We also need to destroy the last object properly here.
+ _storage[_size].~T();
+ return pos;
}
- iterator erase(iterator first,
- iterator last) {
+ iterator erase(iterator first, iterator last) {
Common::copy(last, this->_storage + this->_size, first);
int count = (last - first);
@@ -120,6 +375,62 @@ public:
return first;
}
+ /**
+ * Remove an element
+ */
+ void remove(T element) {
+ for (uint i = 0; i < this->size(); ++i) {
+ if (this->operator[](i) == element) {
+ this->remove_at(i);
+ return;
+ }
+ }
+ }
+
+ /** Check whether the array is empty. */
+ bool empty() const {
+ return (_size == 0);
+ }
+
+ /** Check whether two arrays are identical. */
+ bool operator==(const vector<T> &other) const {
+ if (this == &other)
+ return true;
+ if (_size != other._size)
+ return false;
+ for (size_type i = 0; i < _size; ++i) {
+ if (_storage[i] != other._storage[i])
+ return false;
+ }
+ return true;
+ }
+
+ /** Check if two arrays are different. */
+ bool operator!=(const vector<T> &other) const {
+ return !(*this == other);
+ }
+
+ /** Return an iterator pointing to the first element in the array. */
+ iterator begin() {
+ return _storage;
+ }
+
+ /** Return an iterator pointing past the last element in the array. */
+ iterator end() {
+ return _storage + _size;
+ }
+
+ /** Return a const iterator pointing to the first element in the array. */
+ const_iterator begin() const {
+ return _storage;
+ }
+
+ /** Return a const iterator pointing past the last element in the array. */
+ const_iterator end() const {
+ return _storage + _size;
+ }
+
+
void swap(vector &arr) {
SWAP(this->_capacity, arr._capacity);
SWAP(this->_size, arr._size);
@@ -131,11 +442,11 @@ public:
* the first item, and the predeceding item becomes the last one
*/
void rotate(iterator it) {
- if (it != Common::Array<T>::end()) {
- size_t count = it - Common::Array<T>::begin();
+ if (it != end()) {
+ size_t count = it - begin();
for (size_t ctr = 0; ctr < count; ++ctr) {
- Common::Array<T>::push_back(Common::Array<T>::front());
- Common::Array<T>::remove_at(0);
+ push_back(front());
+ remove_at(0);
}
}
}
@@ -147,76 +458,163 @@ public:
return this->end();
}
reverse_iterator rbegin() {
- return reverse_iterator(this, (int)Common::Array<T>::size() - 1);
+ return reverse_iterator(this, (int)size() - 1);
}
reverse_iterator rend() {
return reverse_iterator(this, -1);
}
const_reverse_iterator rbegin() const {
- return const_reverse_iterator(this, (int)Common::Array<T>::size() - 1);
+ return const_reverse_iterator(this, (int)size() - 1);
}
const_reverse_iterator rend() const {
return const_reverse_iterator(this, -1);
}
const_reverse_iterator crbegin() const {
- return const_reverse_iterator(this, (int)Common::Array<T>::size() - 1);
+ return const_reverse_iterator(this, (int)size() - 1);
}
const_reverse_iterator crend() const {
return const_reverse_iterator(this, -1);
}
- void pop_front() {
- Common::Array<T>::remove_at(0);
+ /** Reserve enough memory in the array so that it can store at least the given number of elements.
+ * The current content of the array is not modified.
+ */
+ void reserve(size_type newCapacity) {
+ if (newCapacity <= _capacity)
+ return;
+
+ T *oldStorage = _storage;
+ allocCapacity(newCapacity);
+
+ if (oldStorage) {
+ // Copy old data
+ uninitialized_move(oldStorage, oldStorage + _size, _storage);
+ freeStorage(oldStorage, _size);
+ }
}
- void resize(size_t newSize) {
- Common::Array<T>::resize(newSize);
+ /** Change the size of the array. */
+ void resize(size_type newSize) {
+ reserve(newSize);
+ for (size_type i = newSize; i < _size; ++i)
+ _storage[i].~T();
+ for (size_type i = _size; i < newSize; ++i)
+ new ((void *)&_storage[i]) T();
+ _size = newSize;
}
+
void resize(size_t newSize, const T elem) {
- size_t oldSize = Common::Array<T>::size();
+ size_t oldSize = size();
resize(newSize);
for (size_t idx = oldSize; idx < newSize; ++idx)
this->operator[](idx) = elem;
}
- T at(size_t index) const {
- return (*this)[index];
- }
-
- /**
- * Adds an item to the array
+ /** Assign to this array the elements between the given iterators from another array,
+ * from @p first included to @p last excluded.
*/
- void insert(const T &element) {
- Common::Array<T>::push_back(element);
+ void assign(const_iterator first, const_iterator last) {
+ resize(distance(first, last)); // FIXME: ineffective?
+ T *dst = _storage;
+ while (first != last)
+ *dst++ = *first++;
}
- /**
- * Adds an item to the array at a specified index
- */
- void insert(iterator pos, const T &element) {
- Common::Array<T>::insert(pos, element);
+protected:
+ /** Round up capacity to the next power of 2.
+ * A minimal capacity of 8 is used.
+ */
+ static size_type roundUpCapacity(size_type capacity) {
+ size_type capa = 8;
+ while (capa < capacity)
+ capa <<= 1;
+ return capa;
}
- /**
- * Adds a range of items at the specified position in the array
- */
- void insert(iterator position, const_iterator first, const_iterator last) {
- int destIndex = position - this->begin();
- for (; first != last; ++first) {
- this->insert_at(destIndex++, *first);
+ /** Allocate a specific capacity for the array. */
+ void allocCapacity(size_type capacity) {
+ _capacity = capacity;
+ if (capacity) {
+ _storage = (T *)malloc(sizeof(T) * capacity);
+ if (!_storage)
+ ::error("Common::vector: failure to allocate %u bytes", capacity * (size_type)sizeof(T));
+ } else {
+ _storage = nullptr;
}
}
+ /** Free the storage used by the array. */
+ void freeStorage(T *storage, const size_type elements) {
+ for (size_type i = 0; i < elements; ++i)
+ storage[i].~T();
+ free(storage);
+ }
+
/**
- * Remove an element
+ * Insert a range of elements coming from this or another array.
+ * Unlike std::vector::insert, this method does not accept
+ * arbitrary iterators, mainly because our iterator system is
+ * seriously limited and does not distinguish between input iterators,
+ * output iterators, forward iterators, or random access iterators.
+ *
+ * So, we simply restrict to vector iterators. Extending this to arbitrary
+ * random access iterators would be trivial.
+ *
+ * Moreover, this method does not handle all cases of inserting a subrange
+ * of an array into itself; this is why it is private for now.
*/
- void remove(T element) {
- for (uint i = 0; i < this->size(); ++i) {
- if (this->operator[](i) == element) {
- this->remove_at(i);
- return;
+ iterator insert_aux(iterator pos, const_iterator first, const_iterator last) {
+ assert(_storage <= pos && pos <= _storage + _size);
+ assert(first <= last);
+ const size_type n = last - first;
+ if (n) {
+ const size_type idx = pos - _storage;
+ if (_size + n > _capacity || (_storage <= first && first <= _storage + _size)) {
+ T *const oldStorage = _storage;
+
+ // If there is not enough space, allocate more.
+ // Likewise, if this is a self-insert, we allocate new
+ // storage to avoid conflicts.
+ allocCapacity(roundUpCapacity(_size + n));
+
+ // Copy the data from the old storage till the position where
+ // we insert new data
+ Common::uninitialized_copy(oldStorage, oldStorage + idx, _storage);
+ // Copy the data we insert
+ Common::uninitialized_copy(first, last, _storage + idx);
+ // Afterwards, copy the old data from the position where we
+ // insert.
+ Common::uninitialized_copy(oldStorage + idx, oldStorage + _size, _storage + idx + n);
+
+ freeStorage(oldStorage, _size);
+ } else if (idx + n <= _size) {
+ // Make room for the new elements by shifting back
+ // existing ones.
+ // 1. Move a part of the data to the uninitialized area
+ Common::uninitialized_copy(_storage + _size - n, _storage + _size, _storage + _size);
+ // 2. Move a part of the data to the initialized area
+ Common::copy_backward(pos, _storage + _size - n, _storage + _size);
+
+ // Insert the new elements.
+ Common::copy(first, last, pos);
+ } else {
+ // Copy the old data from the position till the end to the new
+ // place.
+ Common::uninitialized_copy(pos, _storage + _size, _storage + idx + n);
+
+ // Copy a part of the new data to the position inside the
+ // initialized space.
+ Common::copy(first, first + (_size - idx), pos);
+
+ // Copy a part of the new data to the position inside the
+ // uninitialized space.
+ Common::uninitialized_copy(first + (_size - idx), last, _storage + _size);
}
+
+ // Finally, update the internal state
+ _size += n;
}
+ return pos;
}
};
diff --git a/engines/ags/shared/game/main_game_file.h b/engines/ags/shared/game/main_game_file.h
index 35aeb68ef6a..8eca795ba66 100644
--- a/engines/ags/shared/game/main_game_file.h
+++ b/engines/ags/shared/game/main_game_file.h
@@ -79,11 +79,7 @@ String GetMainGameFileErrorText(MainGameFileErrorType err);
typedef TypedCodeError<MainGameFileErrorType, GetMainGameFileErrorText> MainGameFileError;
typedef ErrorHandle<MainGameFileError> HGameFileError;
-#ifdef AGS_PLATFORM_SCUMMVM
-typedef std::shared_ptr<Stream> UStream;
-#else
typedef std::unique_ptr<Stream> UStream;
-#endif
// MainGameSource defines a successfully opened main game file
struct MainGameSource {
Commit: 8e4254b8391fbbc21c7c4038311ae44de4fd6c61
https://github.com/scummvm/scummvm/commit/8e4254b8391fbbc21c7c4038311ae44de4fd6c61
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:05-07:00
Commit Message:
AGS: Refactored walk-behinds calculation and texture generation
>From upstream ac0c4cea6a6e41238fe74f0753fa6a458f05d954
Changed paths:
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/draw.h
engines/ags/engine/ac/drawing_surface.cpp
engines/ags/engine/ac/room.cpp
engines/ags/engine/ac/walk_behind.cpp
engines/ags/engine/ac/walk_behind.h
engines/ags/engine/main/game_run.cpp
engines/ags/globals.cpp
engines/ags/globals.h
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 1cdfef61680..c781bfa4619 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -391,6 +391,7 @@ void init_game_drawdata() {
size_t actsps_num = _GP(game).numcharacters + MAX_ROOM_OBJECTS;
_GP(actsps).resize(actsps_num);
+
_GP(guibg).resize(_GP(game).numgui);
size_t guio_num = 0;
@@ -407,6 +408,8 @@ void dispose_game_drawdata() {
clear_drawobj_cache();
_GP(actsps).clear();
+ _GP(walkbehindobj).clear();
+
_GP(guibg).clear();
_GP(guiobjbg).clear();
_GP(guiobjddbref).clear();
@@ -429,9 +432,9 @@ void clear_drawobj_cache() {
_G(objcache)[i].image = nullptr;
}
- // cleanup Character + Room object textures
// cleanup Character + Room object textures
for (auto &o : _GP(actsps)) o = ObjTexture();
+ for (auto &o : _GP(walkbehindobj)) o = ObjTexture();
// cleanup GUI and controls textures
for (auto &o : _GP(guibg)) o = ObjTexture();
for (auto &o : _GP(guiobjbg)) o = ObjTexture();
@@ -824,83 +827,6 @@ void put_sprite_list_on_screen(bool in_room);
//
//------------------------------------------------------------------------
-// sort_out_walk_behinds: modifies the supplied sprite by overwriting parts
-// of it with transparent pixels where there are walk-behind areas
-// Returns whether any pixels were updated
-int sort_out_walk_behinds(Bitmap *sprit, int xx, int yy, int basel, int zoom = 100) {
- if (_G(noWalkBehindsAtAll))
- return 0;
-
- if ((!_GP(thisroom).WalkBehindMask->IsMemoryBitmap()) ||
- (!sprit->IsMemoryBitmap()))
- quit("!sort_out_walk_behinds: wb bitmap not linear");
-
- int rr, tmm, toheight; //,tcol;
- // precalculate this to try and shave some time off
- int maskcol = sprit->GetMaskColor();
- int spcoldep = sprit->GetColorDepth();
- int screenhit = _GP(thisroom).WalkBehindMask->GetHeight();
- short *shptr;
- int *loptr;
- int pixelsChanged = 0;
- int ee = 0;
- if (xx < 0)
- ee = 0 - xx;
-
- for (; ee < sprit->GetWidth(); ee++) {
- if (ee + xx >= _GP(thisroom).WalkBehindMask->GetWidth())
- break;
-
- if ((!_G(walkBehindExists)[ee + xx]) ||
- (_G(walkBehindEndY)[ee + xx] <= yy) ||
- (_G(walkBehindStartY)[ee + xx] > yy + sprit->GetHeight()))
- continue;
-
- toheight = sprit->GetHeight();
-
- if (_G(walkBehindStartY)[ee + xx] < yy)
- rr = 0;
- else
- rr = (_G(walkBehindStartY)[ee + xx] - yy);
-
- // Since we will use _getpixel, ensure we only check within the screen
- if (rr + yy < 0)
- rr = 0 - yy;
- if (toheight + yy > screenhit)
- toheight = screenhit - yy;
- if (toheight + yy > _G(walkBehindEndY)[ee + xx])
- toheight = _G(walkBehindEndY)[ee + xx] - yy;
- if (rr < 0)
- rr = 0;
-
- for (; rr < toheight; rr++) {
- // we're ok with _getpixel because we've checked the screen edges
- //tmm = _getpixel(_GP(thisroom).WalkBehindMask,ee+xx,rr+yy);
- // actually, _getpixel is well inefficient, do it ourselves
- // since we know it's 8-bit bitmap
- tmm = _GP(thisroom).WalkBehindMask->GetScanLine(rr + yy)[ee + xx];
- if (tmm < 1) continue;
- if (_G(croom)->walkbehind_base[tmm] <= basel) continue;
-
- pixelsChanged = 1;
- if (spcoldep <= 8)
- sprit->GetScanLineForWriting(rr)[ee] = maskcol;
- else if (spcoldep <= 16) {
- shptr = (short *)&sprit->GetScanLine(rr)[0];
- shptr[ee] = maskcol;
- } else if (spcoldep == 24) {
- char *chptr = (char *)&sprit->GetScanLine(rr)[0];
- memcpy(&chptr[ee * 3], &maskcol, 3);
- } else if (spcoldep <= 32) {
- loptr = (int *)&sprit->GetScanLine(rr)[0];
- loptr[ee] = maskcol;
- } else
- quit("!Sprite colour depth >32 ??");
- }
- }
- return pixelsChanged;
-}
-
void repair_alpha_channel(Bitmap *dest, Bitmap *bgpic) {
// Repair the alpha channel, because sprites may have been drawn
// over it by the buttons, etc
@@ -1377,7 +1303,7 @@ void prepare_objects_for_drawing() {
usebasel += _GP(thisroom).Height;
}
} else if ((!actspsIntact) && (_G(walkBehindMethod) == DrawOverCharSprite)) {
- sort_out_walk_behinds(actsp.Bmp.get(), atxp, atyp, usebasel);
+ walkbehinds_cropout(actsp.Bmp.get(), atxp, atyp, usebasel);
}
if ((!actspsIntact) || (actsp.Ddb == nullptr)) {
@@ -1664,7 +1590,7 @@ void prepare_characters_for_drawing() {
usebasel += _GP(thisroom).Height;
}
} else if (_G(walkBehindMethod) == DrawOverCharSprite) {
- sort_out_walk_behinds(actsp.Bmp.get(), bgX, bgY, usebasel);
+ walkbehinds_cropout(actsp.Bmp.get(), bgX, bgY, usebasel);
}
if ((!usingCachedImage) || (actsp.Ddb == nullptr)) {
@@ -1708,6 +1634,13 @@ Bitmap *get_cached_object_image(int objid) {
return _GP(actsps)[objid].Bmp.get();
}
+void add_walkbehind_image(size_t index, Shared::Bitmap *bmp, int x, int y) {
+ if (_GP(walkbehindobj).size() <= index)
+ _GP(walkbehindobj).resize(index + 1);
+ _GP(walkbehindobj)[index].Bmp.reset(); // don't store bitmap if added this way
+ _GP(walkbehindobj)[index].Ddb = recycle_ddb_bitmap(_GP(walkbehindobj)[index].Ddb, bmp);
+ _GP(walkbehindobj)[index].Pos = Point(x, y);
+}
// Compiles a list of room sprites (characters, objects, background)
void prepare_room_sprites() {
@@ -1724,7 +1657,7 @@ void prepare_room_sprites() {
if (_G(gfxDriver)->RequiresFullRedrawEachFrame()) {
if (_G(current_background_is_dirty) || _G(walkBehindsCachedForBgNum) != _GP(play).bg_frame) {
if (_G(walkBehindMethod) == DrawAsSeparateSprite) {
- update_walk_behind_images();
+ walkbehinds_generate_sprites();
}
}
add_thing_to_draw(_G(roomBackgroundBmp), 0, 0);
@@ -1741,10 +1674,12 @@ void prepare_room_sprites() {
_G(our_eip) = 34;
if (_G(walkBehindMethod) == DrawAsSeparateSprite) {
- for (int ee = 1; ee < MAX_WALK_BEHINDS; ee++) {
- if (_G(walkBehindBitmap)[ee] != nullptr) {
- add_to_sprite_list(_G(walkBehindBitmap)[ee], _G(walkBehindLeft)[ee], _G(walkBehindTop)[ee],
- _G(croom)->walkbehind_base[ee], true);
+ for (int wb = 1 /* 0 is "no area" */;
+ (wb < MAX_WALK_BEHINDS) && (wb < _GP(walkbehindobj).size()); ++wb) {
+ const auto &wbobj = _GP(walkbehindobj)[wb];
+ if (wbobj.Ddb) {
+ add_to_sprite_list(wbobj.Ddb, wbobj.Pos.X, wbobj.Pos.Y,
+ _G(croom)->walkbehind_base[wb], true);
}
}
}
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index 4ec6e5599a7..5c58d92e5cd 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -178,6 +178,9 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
Shared::Bitmap *get_cached_character_image(int charid);
// Returns a cached object image prepared for the render
Shared::Bitmap *get_cached_object_image(int objid);
+// Adds a walk-behind sprite to the list for the given slot
+// (reuses existing texture if possible)
+void add_walkbehind_image(size_t index, Shared::Bitmap *bmp, int x, int y);
void draw_and_invalidate_text(Shared::Bitmap *ds, int x1, int y1, int font, color_t text_color, const char *text);
diff --git a/engines/ags/engine/ac/drawing_surface.cpp b/engines/ags/engine/ac/drawing_surface.cpp
index 7aa64c0c2ca..14355bccaaf 100644
--- a/engines/ags/engine/ac/drawing_surface.cpp
+++ b/engines/ags/engine/ac/drawing_surface.cpp
@@ -66,7 +66,7 @@ void DrawingSurface_Release(ScriptDrawingSurface *sds) {
}
if (sds->roomMaskType > kRoomAreaNone) {
if (sds->roomMaskType == kRoomAreaWalkBehind) {
- recache_walk_behinds();
+ walkbehinds_recalc();
}
sds->roomMaskType = kRoomAreaNone;
}
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 301764865cd..f529de8d7fa 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -521,7 +521,7 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
update_polled_stuff_if_runtime();
redo_walkable_areas();
update_polled_stuff_if_runtime();
- recache_walk_behinds();
+ walkbehinds_recalc();
update_polled_stuff_if_runtime();
_G(our_eip) = 205;
diff --git a/engines/ags/engine/ac/walk_behind.cpp b/engines/ags/engine/ac/walk_behind.cpp
index 401bc096a23..d335b89a033 100644
--- a/engines/ags/engine/ac/walk_behind.cpp
+++ b/engines/ags/engine/ac/walk_behind.cpp
@@ -19,9 +19,11 @@
*
*/
+#include "ags/lib/std/algorithm.h"
#include "ags/engine/ac/walk_behind.h"
#include "ags/shared/ac/common.h"
#include "ags/shared/ac/common_defines.h"
+#include "ags/engine/ac/room_status.h"
#include "ags/engine/ac/game_state.h"
#include "ags/engine/gfx/graphics_driver.h"
#include "ags/shared/gfx/bitmap.h"
@@ -32,93 +34,163 @@ namespace AGS3 {
using namespace AGS::Shared;
using namespace AGS::Engine;
-void update_walk_behind_images() {
- int ee, rr;
- int bpp = (_GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic->GetColorDepth() + 7) / 8;
- Bitmap *wbbmp;
- for (ee = 1; ee < MAX_WALK_BEHINDS; ee++) {
- update_polled_stuff_if_runtime();
-
- if (_G(walkBehindRight)[ee] > 0) {
- wbbmp = BitmapHelper::CreateTransparentBitmap(
- (_G(walkBehindRight)[ee] - _G(walkBehindLeft)[ee]) + 1,
- (_G(walkBehindBottom)[ee] - _G(walkBehindTop)[ee]) + 1,
- _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic->GetColorDepth());
- int yy, startX = _G(walkBehindLeft)[ee], startY = _G(walkBehindTop)[ee];
- for (rr = startX; rr <= _G(walkBehindRight)[ee]; rr++) {
- for (yy = startY; yy <= _G(walkBehindBottom)[ee]; yy++) {
- if (_GP(thisroom).WalkBehindMask->GetScanLine(yy)[rr] == ee) {
- for (int ii = 0; ii < bpp; ii++)
- wbbmp->GetScanLineForWriting(yy - startY)[(rr - startX) * bpp + ii] = _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic->GetScanLine(yy)[rr * bpp + ii];
+
+// An info on vertical column of walk-behind mask, which may contain WB area
+struct WalkBehindColumn {
+ bool Exists = false; // whether any WB area is in this column
+ int Y1 = 0, Y2 = 0; // WB top and bottom Y coords
+};
+
+WalkBehindMethodEnum walkBehindMethod = DrawOverCharSprite;
+std::vector<WalkBehindColumn> walkBehindCols; // precalculated WB positions
+Rect walkBehindAABB[MAX_WALK_BEHINDS]; // WB bounding box
+int walkBehindsCachedForBgNum = 0; // WB textures are for this background
+bool noWalkBehindsAtAll = false; // quick report that no WBs in this room
+bool walk_behind_baselines_changed = false;
+
+
+// Generates walk-behinds as separate sprites
+void walkbehinds_generate_sprites() {
+ const Bitmap *mask = _GP(thisroom).WalkBehindMask.get();
+ const Bitmap *bg = _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic.get();
+
+ const int coldepth = bg->GetColorDepth();
+ Bitmap wbbmp; // temp buffer
+ // Iterate through walk-behinds and generate a texture for each of them
+ for (int wb = 1 /* 0 is "no area" */; wb < MAX_WALK_BEHINDS; ++wb) {
+ const Rect pos = walkBehindAABB[wb];
+ if (pos.Right > 0) {
+ wbbmp.CreateTransparent(pos.GetWidth(), pos.GetHeight(), coldepth);
+ // Copy over all solid pixels belonging to this WB area
+ const int sx = pos.Left, ex = pos.Right, sy = pos.Top, ey = pos.Bottom;
+ for (int y = sy; y <= ey; ++y) {
+ const uint8_t *check_line = mask->GetScanLine(y);
+ const uint8_t *src_line = bg->GetScanLine(y);
+ uint8_t *dst_line = wbbmp.GetScanLineForWriting(y - sy);
+ for (int x = sx; x <= ex; ++x) {
+ if (check_line[x] != wb) continue;
+ switch (coldepth) {
+ case 8:
+ dst_line[(x - sx)] = src_line[x];
+ break;
+ case 16:
+ reinterpret_cast<uint16_t *>(dst_line)[(x - sx)] =
+ reinterpret_cast<const uint16_t *>(src_line)[x];
+ break;
+ case 32:
+ reinterpret_cast<uint32_t *>(dst_line)[(x - sx)] =
+ reinterpret_cast<const uint32_t *>(src_line)[x];
+ break;
+ default: assert(0); break;
}
}
}
-
- update_polled_stuff_if_runtime();
-
- if (_G(walkBehindBitmap)[ee] != nullptr) {
- _G(gfxDriver)->DestroyDDB(_G(walkBehindBitmap)[ee]);
- }
- _G(walkBehindBitmap)[ee] = _G(gfxDriver)->CreateDDBFromBitmap(wbbmp, false);
- delete wbbmp;
+ // Add to walk-behinds image list
+ add_walkbehind_image(wb, &wbbmp, pos.Left, pos.Top);
}
}
- _G(walkBehindsCachedForBgNum) = _GP(play).bg_frame;
+ walkBehindsCachedForBgNum = _GP(play).bg_frame;
}
-
-void recache_walk_behinds() {
- if (_G(walkBehindExists)) {
- free(_G(walkBehindExists));
- free(_G(walkBehindStartY));
- free(_G(walkBehindEndY));
- }
-
- _G(walkBehindExists) = (char *)malloc(_GP(thisroom).WalkBehindMask->GetWidth());
- _G(walkBehindStartY) = (int *)malloc(_GP(thisroom).WalkBehindMask->GetWidth() * sizeof(int));
- _G(walkBehindEndY) = (int *)malloc(_GP(thisroom).WalkBehindMask->GetWidth() * sizeof(int));
- _G(noWalkBehindsAtAll) = 1;
-
- int ee, rr, tmm;
- const int NO_WALK_BEHIND = 100000;
- for (ee = 0; ee < MAX_WALK_BEHINDS; ee++) {
- _G(walkBehindLeft)[ee] = NO_WALK_BEHIND;
- _G(walkBehindTop)[ee] = NO_WALK_BEHIND;
- _G(walkBehindRight)[ee] = 0;
- _G(walkBehindBottom)[ee] = 0;
-
- if (_G(walkBehindBitmap)[ee] != nullptr) {
- _G(gfxDriver)->DestroyDDB(_G(walkBehindBitmap)[ee]);
- _G(walkBehindBitmap)[ee] = nullptr;
+// Edits the given game object's sprite, cutting out pixels covered by walk-behinds;
+// returns whether any pixels were updated;
+bool walkbehinds_cropout(Bitmap *sprit, int sprx, int spry, int basel, int zoom) {
+ if (noWalkBehindsAtAll)
+ return false;
+
+ const int maskcol = sprit->GetMaskColor();
+ const int spcoldep = sprit->GetColorDepth();
+ const int screenhit = _GP(thisroom).WalkBehindMask->GetHeight();
+
+ bool pixels_changed = false;
+ int x = 0;
+ if (sprx < 0)
+ x = 0 - sprx;
+ for (; (x < sprit->GetWidth()) && (x + sprx < _GP(thisroom).WalkBehindMask->GetWidth()); ++x) {
+ const auto &wbcol = walkBehindCols[x + sprx];
+ if ((!wbcol.Exists) ||
+ (wbcol.Y2 <= spry) ||
+ (wbcol.Y1 > spry + sprit->GetHeight()))
+ continue;
+
+ int y;
+ if (wbcol.Y1 < spry)
+ y = 0;
+ else
+ y = (wbcol.Y1 - spry);
+
+ // ensure we only check within the mask
+ int height = sprit->GetHeight();
+ if (y + spry < 0)
+ y = 0 - spry;
+ if (height + spry > screenhit)
+ height = screenhit - spry;
+ if (height + spry > wbcol.Y2)
+ height = wbcol.Y2 - spry;
+ if (y < 0)
+ y = 0;
+
+ for (; y < height; ++y) {
+ const int wb = _GP(thisroom).WalkBehindMask->GetScanLine(y + spry)[x + sprx];
+ if (wb < 1) continue; // "no area"
+ if (_G(croom)->walkbehind_base[wb] <= basel) continue;
+
+ pixels_changed = true;
+ uint8_t *dst_line = sprit->GetScanLineForWriting(y);
+ switch (spcoldep) {
+ case 8:
+ dst_line[x] = maskcol;
+ break;
+ case 16:
+ reinterpret_cast<uint16_t *>(dst_line)[x] = maskcol;
+ break;
+ case 32:
+ reinterpret_cast<uint32_t *>(dst_line)[x] = maskcol;
+ break;
+ default:
+ assert(0);
+ break;
+ }
}
}
+ return pixels_changed;
+}
- update_polled_stuff_if_runtime();
-
- for (ee = 0; ee < _GP(thisroom).WalkBehindMask->GetWidth(); ee++) {
- _G(walkBehindExists)[ee] = 0;
- for (rr = 0; rr < _GP(thisroom).WalkBehindMask->GetHeight(); rr++) {
- tmm = _GP(thisroom).WalkBehindMask->GetScanLine(rr)[ee];
- //tmm = _getpixel(_GP(thisroom).WalkBehindMask,ee,rr);
- if ((tmm >= 1) && (tmm < MAX_WALK_BEHINDS)) {
- if (!_G(walkBehindExists)[ee]) {
- _G(walkBehindStartY)[ee] = rr;
- _G(walkBehindExists)[ee] = tmm;
- _G(noWalkBehindsAtAll) = 0;
+void walkbehinds_recalc() {
+ // Reset all data
+ walkBehindCols.clear();
+ for (int wb = 0; wb < MAX_WALK_BEHINDS; ++wb) {
+ walkBehindAABB[wb] = Rect(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN);
+ }
+ noWalkBehindsAtAll = true;
+
+ // Recalculate everything; note that mask is always 8-bit
+ const Bitmap *mask = _GP(thisroom).WalkBehindMask.get();
+ walkBehindCols.resize(mask->GetWidth());
+ for (int col = 0; col < mask->GetWidth(); ++col) {
+ auto &wbcol = walkBehindCols[col];
+ for (int y = 0; y < mask->GetHeight(); ++y) {
+ int wb = mask->GetScanLine(y)[col];
+ // Valid areas start with index 1, 0 = no area
+ if ((wb >= 1) && (wb < MAX_WALK_BEHINDS)) {
+ if (!wbcol.Exists) {
+ wbcol.Y1 = y;
+ wbcol.Exists = true;
+ noWalkBehindsAtAll = false;
}
- _G(walkBehindEndY)[ee] = rr + 1; // +1 to allow bottom line of screen to work
-
- if (ee < _G(walkBehindLeft)[tmm]) _G(walkBehindLeft)[tmm] = ee;
- if (rr < _G(walkBehindTop)[tmm]) _G(walkBehindTop)[tmm] = rr;
- if (ee > _G(walkBehindRight)[tmm]) _G(walkBehindRight)[tmm] = ee;
- if (rr > _G(walkBehindBottom)[tmm]) _G(walkBehindBottom)[tmm] = rr;
+ wbcol.Y2 = y + 1; // +1 to allow bottom line of screen to work (CHECKME??)
+ // resize the bounding rect
+ walkBehindAABB[wb].Left = std::min(col, walkBehindAABB[wb].Left);
+ walkBehindAABB[wb].Top = std::min(y, walkBehindAABB[wb].Top);
+ walkBehindAABB[wb].Right = std::max(col, walkBehindAABB[wb].Right);
+ walkBehindAABB[wb].Bottom = std::max(y, walkBehindAABB[wb].Bottom);
}
}
}
- if (_G(walkBehindMethod) == DrawAsSeparateSprite) {
- update_walk_behind_images();
+ if (walkBehindMethod == DrawAsSeparateSprite) {
+ walkbehinds_generate_sprites();
}
}
diff --git a/engines/ags/engine/ac/walk_behind.h b/engines/ags/engine/ac/walk_behind.h
index a259a08534d..52ce5894551 100644
--- a/engines/ags/engine/ac/walk_behind.h
+++ b/engines/ags/engine/ac/walk_behind.h
@@ -19,9 +19,13 @@
*
*/
+// Walk-behinds calculation logic.
+
#ifndef AGS_ENGINE_AC_WALK_BEHIND_H
#define AGS_ENGINE_AC_WALK_BEHIND_H
+#include "ags/shared/util/geometry.h"
+
namespace AGS3 {
// A method of rendering walkbehinds on screen:
@@ -36,8 +40,16 @@ enum WalkBehindMethodEnum {
DrawAsSeparateSprite
};
-void update_walk_behind_images();
-void recache_walk_behinds();
+namespace AGS { namespace Shared { class Bitmap; } }
+using namespace AGS; // FIXME later
+
+// Recalculates walk-behind positions
+void walkbehinds_recalc();
+// Generates walk-behinds as separate sprites
+void walkbehinds_generate_sprites();
+// Edits the given game object's sprite, cutting out pixels covered by walk-behinds;
+// returns whether any pixels were updated
+bool walkbehinds_cropout(Shared::Bitmap *sprit, int sprx, int spry, int basel, int zoom = 100);
} // namespace AGS3
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index f2a615f3c98..d0faf8a9bf5 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -49,6 +49,7 @@
#include "ags/engine/ac/room.h"
#include "ags/engine/ac/room_object.h"
#include "ags/engine/ac/room_status.h"
+#include "ags/engine/ac/walk_behind.h"
#include "ags/engine/debugging/debugger.h"
#include "ags/engine/debugging/debug_log.h"
#include "ags/engine/device/mouse_w32.h"
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index fbe3dd24b00..40c9340d512 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -174,6 +174,7 @@ Globals::Globals() {
MAX_DYNAMIC_SURFACES, (AGS::Shared::Bitmap *)nullptr);
_actsps = new std::vector<ObjTexture>();
+ _walkbehindobj = new std::vector<ObjTexture>();
_guibg = new std::vector<ObjTexture>();
_guiobjbg = new std::vector<ObjTexture>();
@@ -428,6 +429,7 @@ Globals::~Globals() {
delete _sprlist;
delete _thingsToDrawList;
delete _actsps;
+ delete _walkbehindobj;
delete _guibg;
delete _guiobjbg;
delete _guiobjddbref;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 52aa0442ffb..dcdd310d885 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -579,6 +579,8 @@ public:
// actsps is used for temporary storage of the bitamp image
// of the latest version of the sprite
std::vector<ObjTexture> *_actsps;
+ // Walk-behind textures (3D renderers only)
+ std::vector<ObjTexture> *_walkbehindobj;
// GUI surfaces
std::vector<ObjTexture> *_guibg;
// GUI control surfaces
Commit: d161f11e549e6c9b525f94168864a39626a587d5
https://github.com/scummvm/scummvm/commit/d161f11e549e6c9b525f94168864a39626a587d5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:06-07:00
Commit Message:
AGS: Further simplify walkbehinds_cropout()
>From upstream 08a382f17f4c07e615308caba5a16203729e7bc9
Changed paths:
engines/ags/engine/ac/walk_behind.cpp
diff --git a/engines/ags/engine/ac/walk_behind.cpp b/engines/ags/engine/ac/walk_behind.cpp
index d335b89a033..62e5f73cdb3 100644
--- a/engines/ags/engine/ac/walk_behind.cpp
+++ b/engines/ags/engine/ac/walk_behind.cpp
@@ -101,37 +101,23 @@ bool walkbehinds_cropout(Bitmap *sprit, int sprx, int spry, int basel, int zoom)
const int maskcol = sprit->GetMaskColor();
const int spcoldep = sprit->GetColorDepth();
- const int screenhit = _GP(thisroom).WalkBehindMask->GetHeight();
bool pixels_changed = false;
- int x = 0;
- if (sprx < 0)
- x = 0 - sprx;
- for (; (x < sprit->GetWidth()) && (x + sprx < _GP(thisroom).WalkBehindMask->GetWidth()); ++x) {
+ // pass along the sprite's pixels, but skip those that lie outside the mask
+ for (int x = std::max(0, 0 - sprx);
+ (x < sprit->GetWidth()) && (x + sprx < _GP(thisroom).WalkBehindMask->GetWidth()); ++x) {
+ // select the WB column at this x
const auto &wbcol = walkBehindCols[x + sprx];
+ // skip if no area, or sprite lies outside of all areas in this column
if ((!wbcol.Exists) ||
(wbcol.Y2 <= spry) ||
(wbcol.Y1 > spry + sprit->GetHeight()))
continue;
- int y;
- if (wbcol.Y1 < spry)
- y = 0;
- else
- y = (wbcol.Y1 - spry);
-
- // ensure we only check within the mask
- int height = sprit->GetHeight();
- if (y + spry < 0)
- y = 0 - spry;
- if (height + spry > screenhit)
- height = screenhit - spry;
- if (height + spry > wbcol.Y2)
- height = wbcol.Y2 - spry;
- if (y < 0)
- y = 0;
-
- for (; y < height; ++y) {
+ // ensure we only check within the valid areas (between Y1 and Y2)
+ // we assume that Y1 and Y2 are always within the mask
+ for (int y = std::max(0, wbcol.Y1 - spry);
+ (y < sprit->GetHeight()) && (y + spry < wbcol.Y2); ++y) {
const int wb = _GP(thisroom).WalkBehindMask->GetScanLine(y + spry)[x + sprx];
if (wb < 1) continue; // "no area"
if (_G(croom)->walkbehind_base[wb] <= basel) continue;
Commit: cfefb80461109b07956a4ca005b16edb31635edf
https://github.com/scummvm/scummvm/commit/cfefb80461109b07956a4ca005b16edb31635edf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:06-07:00
Commit Message:
AGS: Moved font renderer shutdown after the game data disposal
>From upstream 0914030ff28647262e53d611f8de8e9b5f3aca16
Changed paths:
engines/ags/engine/main/quit.cpp
diff --git a/engines/ags/engine/main/quit.cpp b/engines/ags/engine/main/quit.cpp
index 23de13a9473..ae73e19bd00 100644
--- a/engines/ags/engine/main/quit.cpp
+++ b/engines/ags/engine/main/quit.cpp
@@ -220,9 +220,6 @@ void quit_free() {
_G(our_eip) = 9901;
- shutdown_font_renderer();
- _G(our_eip) = 9902;
-
_GP(spriteset).Reset();
_G(our_eip) = 9908;
@@ -240,7 +237,9 @@ void quit_free() {
// release backed library
// WARNING: no Allegro objects should remain in memory after this,
// if their destruction is called later, program will crash!
+ shutdown_font_renderer();
allegro_exit();
+ sys_main_shutdown();
_G(platform)->PostAllegroExit();
Commit: da1178d905e35c0a64c816b37fe46eb0f1de291a
https://github.com/scummvm/scummvm/commit/da1178d905e35c0a64c816b37fe46eb0f1de291a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:06-07:00
Commit Message:
AGS: Implemented proper HasAlphaChannel for all gui controls
>From upstream 83306ee321e127368a41068f32bd4899ae00223e
Changed paths:
engines/ags/engine/ac/display.cpp
engines/ags/engine/ac/display.h
engines/ags/engine/ac/gui_inv.cpp
engines/ags/engine/gui/gui_engine.cpp
engines/ags/shared/font/fonts.cpp
engines/ags/shared/font/fonts.h
engines/ags/shared/gui/gui_button.cpp
engines/ags/shared/gui/gui_button.h
engines/ags/shared/gui/gui_inv.h
engines/ags/shared/gui/gui_label.cpp
engines/ags/shared/gui/gui_label.h
engines/ags/shared/gui/gui_listbox.cpp
engines/ags/shared/gui/gui_listbox.h
engines/ags/shared/gui/gui_textbox.cpp
engines/ags/shared/gui/gui_textbox.h
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index a0553554bc9..442044ba925 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -444,7 +444,7 @@ int GetTextDisplayTime(const char *text, int canberel) {
}
bool ShouldAntiAliasText() {
- return (_GP(game).options[OPT_ANTIALIASFONTS] != 0 || ::AGS::g_vm->_forceTextAA);
+ return (_GP(game).GetColorDepth() >= 24) && (_GP(game).options[OPT_ANTIALIASFONTS] != 0);
}
void wouttextxy_AutoOutline(Bitmap *ds, size_t font, int32_t color, const char *texx, int &xxp, int &yyp) {
diff --git a/engines/ags/engine/ac/display.h b/engines/ags/engine/ac/display.h
index b5d5151a9ae..1a30cda060d 100644
--- a/engines/ags/engine/ac/display.h
+++ b/engines/ags/engine/ac/display.h
@@ -44,7 +44,6 @@ void _display_at(int xx, int yy, int wii, const char *text, int disp_type, int a
// and clip was started, or string cleaned from voice-over tags which is safe to display on screen.
// Returns whether voice-over clip was started successfully.
bool try_auto_play_speech(const char *text, const char *&replace_text, int charid);
-bool ShouldAntiAliasText();
// Calculates meaningful length of the displayed text
int GetTextDisplayLength(const char *text);
// Calculates number of game loops for displaying a text on screen
diff --git a/engines/ags/engine/ac/gui_inv.cpp b/engines/ags/engine/ac/gui_inv.cpp
index 8c63a31eeb5..813f581adee 100644
--- a/engines/ags/engine/ac/gui_inv.cpp
+++ b/engines/ags/engine/ac/gui_inv.cpp
@@ -32,6 +32,12 @@ namespace AGS3 {
namespace AGS {
namespace Shared {
+bool GUIInvWindow::HasAlphaChannel() const {
+ // We would have to test every inventory item's graphic to tell precisely,
+ // so just test game color depth instead:
+ return _GP(game).GetColorDepth() == 32;
+}
+
int GUIInvWindow::GetCharacterId() const {
if (CharId < 0)
return _GP(game).playercharacter;
diff --git a/engines/ags/engine/gui/gui_engine.cpp b/engines/ags/engine/gui/gui_engine.cpp
index 61a08412193..3363a82079b 100644
--- a/engines/ags/engine/gui/gui_engine.cpp
+++ b/engines/ags/engine/gui/gui_engine.cpp
@@ -30,6 +30,7 @@
#include "ags/shared/font/fonts.h"
#include "ags/shared/gui/gui_main.h"
#include "ags/shared/gui/gui_button.h"
+#include "ags/shared/gui/gui_inv.h"
#include "ags/shared/gui/gui_label.h"
#include "ags/shared/gui/gui_listbox.h"
#include "ags/shared/gui/gui_textbox.h"
diff --git a/engines/ags/shared/font/fonts.cpp b/engines/ags/shared/font/fonts.cpp
index 600aa7c3b22..e4cf1fce898 100644
--- a/engines/ags/shared/font/fonts.cpp
+++ b/engines/ags/shared/font/fonts.cpp
@@ -188,6 +188,12 @@ void set_font_outline(size_t font_number, int outline_type,
_GP(fonts)[font_number].Info.AutoOutlineThickness = thickness;
}
+bool is_font_antialiased(size_t font_number) {
+ if (font_number >= _GP(fonts).size())
+ return false;
+ return ShouldAntiAliasText() && !is_bitmap_font(font_number);
+}
+
int get_font_height(size_t fontNumber) {
if (fontNumber >= _GP(fonts).size() || !_GP(fonts)[fontNumber].Renderer)
return 0;
diff --git a/engines/ags/shared/font/fonts.h b/engines/ags/shared/font/fonts.h
index d5bbbb2f35c..0643e6eb441 100644
--- a/engines/ags/shared/font/fonts.h
+++ b/engines/ags/shared/font/fonts.h
@@ -116,6 +116,7 @@ int get_text_lines_surf_height(size_t fontNumber, size_t numlines);
// Set font's outline type
void set_font_outline(size_t font_number, int outline_type,
enum FontInfo::AutoOutlineStyle style = FontInfo::kSquared, int thickness = 1);
+bool is_font_antialiased(size_t font_number);
// Outputs a single line of text on the defined position on bitmap, using defined font, color and parameters
void wouttextxy(Shared::Bitmap *ds, int xxx, int yyy, size_t fontNumber, color_t text_color, const char *texx);
// Assigns FontInfo to the font
@@ -136,6 +137,9 @@ void wfreefont(size_t fontNumber);
// Free all fonts data
void free_all_fonts();
+// Tells if the text should be antialiased when possible
+bool ShouldAntiAliasText();
+
// SplitLines class represents a list of lines and is meant to reduce
// subsequent memory (de)allocations if used often during game loops
// and drawing. For that reason it is not equivalent to std::vector,
diff --git a/engines/ags/shared/gui/gui_button.cpp b/engines/ags/shared/gui/gui_button.cpp
index 64dd5e3dc7d..63d986c59c0 100644
--- a/engines/ags/shared/gui/gui_button.cpp
+++ b/engines/ags/shared/gui/gui_button.cpp
@@ -21,6 +21,7 @@
#include "ags/shared/ac/sprite_cache.h"
#include "ags/shared/ac/game_struct_defines.h"
+#include "ags/shared/font/fonts.h"
#include "ags/shared/gui/gui_button.h"
#include "ags/shared/gui/gui_main.h" // TODO: extract helper functions
#include "ags/shared/util/stream.h"
@@ -28,7 +29,6 @@
#include "ags/globals.h"
namespace AGS3 {
-
namespace AGS {
namespace Shared {
@@ -82,6 +82,11 @@ GUIButton::GUIButton() {
_scEventArgs[0] = "GUIControl *control, MouseButton button";
}
+bool GUIButton::HasAlphaChannel() const {
+ return ((CurrentImage > 0) && is_sprite_alpha(CurrentImage)) ||
+ (!_unnamed && is_font_antialiased(Font));
+}
+
const String &GUIButton::GetText() const {
return _text;
}
@@ -94,10 +99,6 @@ bool GUIButton::IsClippingImage() const {
return (Flags & kGUICtrl_Clip) != 0;
}
-bool GUIButton::HasAlphaChannel() const {
- return is_sprite_alpha(CurrentImage);
-}
-
Rect GUIButton::CalcGraphicRect(bool clipped) {
if (clipped)
return RectWH(X, Y, Width, Height);
diff --git a/engines/ags/shared/gui/gui_button.h b/engines/ags/shared/gui/gui_button.h
index e83f0242a38..2fe0ae77bd3 100644
--- a/engines/ags/shared/gui/gui_button.h
+++ b/engines/ags/shared/gui/gui_button.h
@@ -62,10 +62,10 @@ class GUIButton : public GUIObject {
public:
GUIButton();
+ bool HasAlphaChannel() const override;
const String &GetText() const;
bool IsImageButton() const;
bool IsClippingImage() const;
- bool HasAlphaChannel() const override;
// Operations
Rect CalcGraphicRect(bool clipped) override;
diff --git a/engines/ags/shared/gui/gui_inv.h b/engines/ags/shared/gui/gui_inv.h
index 6d4f4e814e6..bc0e7045c7e 100644
--- a/engines/ags/shared/gui/gui_inv.h
+++ b/engines/ags/shared/gui/gui_inv.h
@@ -33,6 +33,7 @@ class GUIInvWindow : public GUIObject {
public:
GUIInvWindow();
+ bool HasAlphaChannel() const override;
// This function has distinct implementations in Engine and Editor
int GetCharacterId() const;
diff --git a/engines/ags/shared/gui/gui_label.cpp b/engines/ags/shared/gui/gui_label.cpp
index 83719a81e59..14957b4d73e 100644
--- a/engines/ags/shared/gui/gui_label.cpp
+++ b/engines/ags/shared/gui/gui_label.cpp
@@ -41,6 +41,10 @@ GUILabel::GUILabel() {
_scEventCount = 0;
}
+bool GUILabel::HasAlphaChannel() const {
+ return is_font_antialiased(Font);
+}
+
String GUILabel::GetText() const {
return Text;
}
diff --git a/engines/ags/shared/gui/gui_label.h b/engines/ags/shared/gui/gui_label.h
index 5a2333c9cc3..e03ce20cfd5 100644
--- a/engines/ags/shared/gui/gui_label.h
+++ b/engines/ags/shared/gui/gui_label.h
@@ -37,6 +37,7 @@ class GUILabel : public GUIObject {
public:
GUILabel();
+ bool HasAlphaChannel() const override;
// Gets label's text property in original set form (with macros etc)
String GetText() const;
// Gets which macro are contained within label's text
diff --git a/engines/ags/shared/gui/gui_listbox.cpp b/engines/ags/shared/gui/gui_listbox.cpp
index 47524f979db..3a66f5d6f0c 100644
--- a/engines/ags/shared/gui/gui_listbox.cpp
+++ b/engines/ags/shared/gui/gui_listbox.cpp
@@ -49,6 +49,10 @@ GUIListBox::GUIListBox() {
_scEventArgs[0] = "GUIControl *control";
}
+bool GUIListBox::HasAlphaChannel() const {
+ return is_font_antialiased(Font);
+}
+
int GUIListBox::GetItemAt(int x, int y) const {
if (RowHeight <= 0 || IsInRightMargin(x))
return -1;
diff --git a/engines/ags/shared/gui/gui_listbox.h b/engines/ags/shared/gui/gui_listbox.h
index 6fc08cda7ee..d4e8fd1613a 100644
--- a/engines/ags/shared/gui/gui_listbox.h
+++ b/engines/ags/shared/gui/gui_listbox.h
@@ -34,6 +34,7 @@ class GUIListBox : public GUIObject {
public:
GUIListBox();
+ bool HasAlphaChannel() const override;
bool AreArrowsShown() const;
bool IsBorderShown() const;
bool IsSvgIndex() const;
diff --git a/engines/ags/shared/gui/gui_textbox.cpp b/engines/ags/shared/gui/gui_textbox.cpp
index 1f7a7ade5e5..137c2261be7 100644
--- a/engines/ags/shared/gui/gui_textbox.cpp
+++ b/engines/ags/shared/gui/gui_textbox.cpp
@@ -43,6 +43,10 @@ GUITextBox::GUITextBox() {
_scEventArgs[0] = "GUIControl *control";
}
+bool GUITextBox::HasAlphaChannel() const {
+ return is_font_antialiased(Font);
+}
+
bool GUITextBox::IsBorderShown() const {
return (TextBoxFlags & kTextBox_ShowBorder) != 0;
}
diff --git a/engines/ags/shared/gui/gui_textbox.h b/engines/ags/shared/gui/gui_textbox.h
index b90bfd59c8c..ed285651847 100644
--- a/engines/ags/shared/gui/gui_textbox.h
+++ b/engines/ags/shared/gui/gui_textbox.h
@@ -34,6 +34,7 @@ class GUITextBox : public GUIObject {
public:
GUITextBox();
+ bool HasAlphaChannel() const override;
bool IsBorderShown() const;
// Operations
Commit: d767293a3229de8863428ba4fb22edc278f05e56
https://github.com/scummvm/scummvm/commit/d767293a3229de8863428ba4fb22edc278f05e56
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:06-07:00
Commit Message:
AGS: Updated build version (3.6.0.24)
>From upstream c0fe840f2ad123bbb1071e42f8449bf8fa80b58a
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 81073776aeb..280071ee0f1 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.23"
+#define ACI_VERSION_STR "3.6.0.24"
#if defined (RC_INVOKED) // for MSVC resource compiler
-#define ACI_VERSION_MSRC_DEF 3.6.0.23
+#define ACI_VERSION_MSRC_DEF 3.6.0.24
#endif
#define SPECIAL_VERSION ""
Commit: 480be2134b3d565964e43819da8da2abb632b8af
https://github.com/scummvm/scummvm/commit/480be2134b3d565964e43819da8da2abb632b8af
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:06-07:00
Commit Message:
AGS: Added script instance thread stack, replacing current_instance
>From upstream f3443cb7a4ae5858e5d2d28131aaf6cf138bc0ec
Changed paths:
A engines/ags/lib/std/stack.h
engines/ags/engine/debugging/debug.cpp
engines/ags/engine/debugging/debugger.h
engines/ags/engine/script/cc_instance.cpp
engines/ags/engine/script/cc_instance.h
engines/ags/engine/script/executing_script.cpp
engines/ags/engine/script/script.cpp
engines/ags/engine/script/script.h
engines/ags/engine/script/script_runtime.cpp
engines/ags/globals.cpp
engines/ags/globals.h
diff --git a/engines/ags/engine/debugging/debug.cpp b/engines/ags/engine/debugging/debug.cpp
index 05f14fd2583..ca2981a969d 100644
--- a/engines/ags/engine/debugging/debug.cpp
+++ b/engines/ags/engine/debugging/debug.cpp
@@ -326,15 +326,6 @@ String get_cur_script(int numberOfLinesOfCallStack) {
return callstack;
}
-bool get_script_position(ScriptPosition &script_pos) {
- ccInstance *cur_instance = ccInstance::GetCurrentInstance();
- if (cur_instance) {
- cur_instance->GetScriptPosition(script_pos);
- return true;
- }
- return false;
-}
-
struct Breakpoint {
char scriptName[80];
int lineNumber;
diff --git a/engines/ags/engine/debugging/debugger.h b/engines/ags/engine/debugging/debugger.h
index ee393b854af..0929797b366 100644
--- a/engines/ags/engine/debugging/debugger.h
+++ b/engines/ags/engine/debugging/debugger.h
@@ -34,7 +34,6 @@ bool send_message_to_editor(const char *msg);
bool send_exception_to_editor(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/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index 83924c519fc..640b06efae2 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -182,7 +182,7 @@ struct FunctionCallStack {
ccInstance *ccInstance::GetCurrentInstance() {
- return _G(current_instance);
+ return _GP(InstThreads).size() > 0 ? _GP(InstThreads).top() : nullptr;
}
ccInstance *ccInstance::CreateFromScript(PScript scri) {
@@ -321,50 +321,41 @@ int ccInstance::CallScriptFunction(const char *funcname, int32_t numargs, const
return -2;
}
+ // Prepare instance for run
+ flags &= ~INSTF_ABORTED;
// Allow to pass less parameters if script callback has less declared args
numargs = std::min(numargs, export_args);
-
- //numargs++; // account for return address
- flags &= ~INSTF_ABORTED;
-
// object pointer needs to start zeroed
registers[SREG_OP].SetDynamicObject(nullptr, nullptr);
-
- ccInstance *currentInstanceWas = _G(current_instance);
registers[SREG_SP].SetStackPtr(&stack[0]);
stackdata_ptr = stackdata;
// NOTE: Pushing parameters to stack in reverse order
ASSERT_STACK_SPACE_AVAILABLE(numargs + 1 /* return address */)
- for (int i = numargs - 1; i >= 0; --i) {
- PushValueToStack(params[i]);
- }
+ for (int i = numargs - 1; i >= 0; --i) {
+ PushValueToStack(params[i]);
+ }
PushValueToStack(RuntimeScriptValue().SetInt32(0)); // return address on stack
- if (_G(ccError)) {
- return -1;
- }
- runningInst = this;
+ _GP(InstThreads).push(this); // push instance thread
+ runningInst = this;
int reterr = Run(startat);
+ // Cleanup before returning, even if error
ASSERT_STACK_SIZE(numargs);
PopValuesFromStack(numargs);
pc = 0;
- _G(current_instance) = currentInstanceWas;
-
- if (_G(abort_engine))
- return -1;
+ _GP(InstThreads).pop(); // pop instance thread
+ if (reterr != 0)
+ return reterr;
// NOTE that if proper multithreading is added this will need
- // to be reconsidered, since the GC could be run in the middle
- // of a RET from a function or something where there is an
+ // to be reconsidered, since the GC could be run in the middle
+ // of a RET from a function or something where there is an
// object with ref count 0 that is in use
_GP(pool).RunGarbageCollectionIfAppropriate();
if (_G(new_line_hook))
_G(new_line_hook)(nullptr, 0);
- if (reterr)
- return -6;
-
if (flags & INSTF_ABORTED) {
flags &= ~INSTF_ABORTED;
@@ -419,7 +410,6 @@ int ccInstance::Run(int32_t curpc) {
int loopIterationCheckDisabled = 0;
thisbase[0] = 0;
funcstart[0] = pc;
- _G(current_instance) = this;
ccInstance *codeInst = runningInst;
bool write_debug_dump = ccGetOption(SCOPT_DEBUGRUN) ||
(gDebugLevel > 0 && DebugMan.isDebugChannelEnabled(::AGS::kDebugScript));
@@ -609,7 +599,6 @@ int ccInstance::Run(int32_t curpc) {
returnValue = registers[SREG_AX].IValue;
return 0;
}
- _G(current_instance) = this;
POP_CALL_STACK;
continue; // continue so that the PC doesn't get overwritten
}
@@ -1038,7 +1027,6 @@ int ccInstance::Run(int32_t curpc) {
}
registers[SREG_AX] = return_value;
- _G(current_instance) = this;
next_call_needs_object = 0;
num_args_to_func = -1;
break;
diff --git a/engines/ags/engine/script/cc_instance.h b/engines/ags/engine/script/cc_instance.h
index e7f005691e0..8b468f59e34 100644
--- a/engines/ags/engine/script/cc_instance.h
+++ b/engines/ags/engine/script/cc_instance.h
@@ -161,8 +161,6 @@ public:
// Call an exported function in the script
int CallScriptFunction(const char *funcname, int32_t num_params, const RuntimeScriptValue *params);
- // Begin executing script starting from the given bytecode index
- int Run(int32_t curpc);
// Get the script's execution position and callstack as human-readable text
Shared::String GetCallStack(int maxLines);
@@ -193,6 +191,8 @@ protected:
bool CreateRuntimeCodeFixups(const ccScript *scri);
//bool ReadOperation(ScriptOperation &op, int32_t at_pc);
+ // Begin executing script starting from the given bytecode index
+ int Run(int32_t curpc);
// Runtime fixups
//bool FixupArgument(intptr_t code_value, char fixup_type, RuntimeScriptValue &argument);
diff --git a/engines/ags/engine/script/executing_script.cpp b/engines/ags/engine/script/executing_script.cpp
index 0222546c91f..6b0983ad47c 100644
--- a/engines/ags/engine/script/executing_script.cpp
+++ b/engines/ags/engine/script/executing_script.cpp
@@ -22,6 +22,7 @@
#include "ags/engine/script/executing_script.h"
#include "ags/engine/debugging/debug_log.h"
#include "ags/engine/debugging/debugger.h"
+#include "ags/engine/script/script.h"
namespace AGS3 {
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index cda695e5312..409fd59405b 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -890,4 +890,13 @@ void run_unhandled_event(int evnt) {
}
}
+bool get_script_position(ScriptPosition &script_pos) {
+ ccInstance *cur_instance = ccInstance::GetCurrentInstance();
+ if (cur_instance) {
+ cur_instance->GetScriptPosition(script_pos);
+ return true;
+ }
+ return false;
+}
+
} // namespace AGS3
diff --git a/engines/ags/engine/script/script.h b/engines/ags/engine/script/script.h
index d7b2f64dd96..3b221bc2f7f 100644
--- a/engines/ags/engine/script/script.h
+++ b/engines/ags/engine/script/script.h
@@ -86,6 +86,9 @@ InteractionVariable *FindGraphicalVariable(const char *varName);
void run_unhandled_event(int evnt);
void can_run_delayed_command();
+// Gets current running script position
+bool get_script_position(ScriptPosition &script_pos);
+
} // namespace AGS3
#endif
diff --git a/engines/ags/engine/script/script_runtime.cpp b/engines/ags/engine/script/script_runtime.cpp
index 8fb0541ac75..292cd27d63a 100644
--- a/engines/ags/engine/script/script_runtime.cpp
+++ b/engines/ags/engine/script/script_runtime.cpp
@@ -124,8 +124,9 @@ void ccSetScriptAliveTimer(int numloop) {
}
void ccNotifyScriptStillAlive() {
- if (_G(current_instance) != nullptr)
- _G(current_instance)->flags |= INSTF_RUNNING;
+ ccInstance *cur_inst = ccInstance::GetCurrentInstance();
+ if (cur_inst)
+ cur_inst->flags |= INSTF_RUNNING;
}
void ccSetDebugHook(new_line_hook_type jibble) {
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 40c9340d512..d4da8007e60 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -129,6 +129,7 @@ Globals::Globals() {
_animbuts = new std::vector<AnimatingGUIButton>();
// cc_instance.cpp globals
+ _InstThreads = new std::stack<ccInstance *>();
_GlobalReturnValue = new RuntimeScriptValue();
// cc_options.cpp globals
@@ -396,6 +397,7 @@ Globals::~Globals() {
delete _animbuts;
// cc_instance.cpp globals
+ delete _InstThreads;
delete _GlobalReturnValue;
delete _scriptDumpFile;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index dcdd310d885..f14d33d7fbe 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -25,6 +25,7 @@
#include "ags/shared/core/platform.h"
#define AGS_PLATFORM_DEFINES_PSP_VARS (AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID)
+#include "ags/lib/std/stack.h"
#include "ags/shared/ac/game_version.h"
#include "ags/shared/util/stdio_compat.h"
#include "ags/shared/util/string.h"
@@ -369,7 +370,11 @@ public:
* @{
*/
- ccInstance *_current_instance = nullptr;
+ // Instance thread stack holds a list of running or suspended script instances;
+ // In AGS currently only one thread is running, others are waiting in the queue.
+ // An example situation is repeatedly_execute_always callback running while
+ // another instance is waiting at the blocking action or Wait().
+ std::stack<ccInstance *> *_InstThreads;
// [IKM] 2012-10-21:
// NOTE: This is temporary solution (*sigh*, one of many) which allows certain
// exported functions return value as a RuntimeScriptValue object;
diff --git a/engines/ags/lib/std/stack.h b/engines/ags/lib/std/stack.h
new file mode 100644
index 00000000000..4a9723dbbbe
--- /dev/null
+++ b/engines/ags/lib/std/stack.h
@@ -0,0 +1,36 @@
+/* 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_STD_STACK_H
+#define AGS_STD_STACK_H
+
+#include "common/stack.h"
+
+namespace AGS3 {
+namespace std {
+
+template<class T>
+using stack = Common::Stack<T>;
+
+} // namespace std
+} // namespace AGS3
+
+#endif
Commit: a2a5f2575db5ee36732850242ce15fc8f01aacb0
https://github.com/scummvm/scummvm/commit/a2a5f2575db5ee36732850242ce15fc8f01aacb0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:07-07:00
Commit Message:
AGS: Reorganized few cc_ headers
>From upstream ea1f8b9ece69fc7c49c4d3aa7b9af51c4ca736e5
Changed paths:
A engines/ags/shared/script/cc_common.cpp
A engines/ags/shared/script/cc_common.h
A engines/ags/shared/script/cc_internal.h
R engines/ags/shared/script/cc_error.cpp
R engines/ags/shared/script/cc_error.h
R engines/ags/shared/script/cc_options.cpp
R engines/ags/shared/script/cc_options.h
R engines/ags/shared/script/script_common.h
engines/ags/ags.cpp
engines/ags/console.cpp
engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp
engines/ags/engine/ac/dynobj/managed_object_pool.cpp
engines/ags/engine/ac/event.cpp
engines/ags/engine/ac/global_debug.cpp
engines/ags/engine/ac/room.cpp
engines/ags/engine/debugging/debug.cpp
engines/ags/engine/game/game_init.cpp
engines/ags/engine/game/savegame.cpp
engines/ags/engine/game/savegame_components.cpp
engines/ags/engine/game/savegame_v321.cpp
engines/ags/engine/main/game_file.cpp
engines/ags/engine/script/cc_instance.cpp
engines/ags/engine/script/cc_instance.h
engines/ags/engine/script/runtime_script_value.cpp
engines/ags/engine/script/script.cpp
engines/ags/engine/script/script_api.cpp
engines/ags/engine/script/script_engine.cpp
engines/ags/engine/script/script_runtime.cpp
engines/ags/globals.cpp
engines/ags/module.mk
engines/ags/shared/game/main_game_file.cpp
engines/ags/shared/game/room_file.cpp
engines/ags/shared/script/cc_script.cpp
diff --git a/engines/ags/ags.cpp b/engines/ags/ags.cpp
index 05fa1c74ba3..413367bc944 100644
--- a/engines/ags/ags.cpp
+++ b/engines/ags/ags.cpp
@@ -56,7 +56,7 @@
#include "ags/engine/ac/route_finder.h"
#include "ags/shared/core/asset_manager.h"
#include "ags/shared/util/directory.h"
-#include "ags/shared/script/cc_options.h"
+#include "ags/shared/script/cc_common.h"
#ifdef ENABLE_AGS_TESTS
#include "ags/tests/test_all.h"
diff --git a/engines/ags/console.cpp b/engines/ags/console.cpp
index 285e8567ad3..02a274d832f 100644
--- a/engines/ags/console.cpp
+++ b/engines/ags/console.cpp
@@ -24,7 +24,7 @@
#include "ags/globals.h"
#include "ags/shared/ac/sprite_cache.h"
#include "ags/shared/gfx/allegro_bitmap.h"
-#include "ags/shared/script/cc_options.h"
+#include "ags/shared/script/cc_common.h"
#include "image/png.h"
namespace AGS {
diff --git a/engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp b/engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp
index 981dbfaacfd..fa8e95b3746 100644
--- a/engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp
@@ -33,15 +33,11 @@
//
//=============================================================================
-//#define DEBUG_MANAGED_OBJECTS
-
-//include <stdlib.h>
-//include <string.h>
#include "ags/engine/ac/dynobj/cc_dynamic_object.h"
#include "ags/engine/ac/dynobj/managed_object_pool.h"
#include "ags/shared/debugging/out.h"
-#include "ags/shared/script/cc_error.h"
-#include "ags/shared/script/script_common.h"
+#include "ags/shared/script/cc_common.h"
+#include "ags/shared/script/cc_internal.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
diff --git a/engines/ags/engine/ac/dynobj/managed_object_pool.cpp b/engines/ags/engine/ac/dynobj/managed_object_pool.cpp
index 94909fa9523..dd794a7e433 100644
--- a/engines/ags/engine/ac/dynobj/managed_object_pool.cpp
+++ b/engines/ags/engine/ac/dynobj/managed_object_pool.cpp
@@ -24,8 +24,8 @@
#include "ags/engine/ac/dynobj/cc_dynamic_array.h" // globalDynamicArray, constants
#include "ags/shared/debugging/out.h"
#include "ags/shared/util/string_utils.h" // fputstring, etc
-#include "ags/shared/script/cc_error.h"
-#include "ags/shared/script/script_common.h"
+#include "ags/shared/script/cc_common.h"
+#include "ags/shared/script/cc_internal.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
diff --git a/engines/ags/engine/ac/event.cpp b/engines/ags/engine/ac/event.cpp
index 924a2cd79a3..fddd41b67e7 100644
--- a/engines/ags/engine/ac/event.cpp
+++ b/engines/ags/engine/ac/event.cpp
@@ -30,7 +30,7 @@
#include "ags/engine/ac/gui.h"
#include "ags/engine/ac/room_status.h"
#include "ags/engine/ac/screen.h"
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/engine/platform/base/ags_platform_driver.h"
#include "ags/plugins/ags_plugin.h"
#include "ags/plugins/plugin_engine.h"
diff --git a/engines/ags/engine/ac/global_debug.cpp b/engines/ags/engine/ac/global_debug.cpp
index f36e3b2ec90..20f75b3a816 100644
--- a/engines/ags/engine/ac/global_debug.cpp
+++ b/engines/ags/engine/ac/global_debug.cpp
@@ -37,12 +37,12 @@
#include "ags/engine/ac/walkable_area.h"
#include "ags/engine/gfx/gfxfilter.h"
#include "ags/engine/gui/gui_dialog.h"
-#include "ags/shared/script/cc_options.h"
#include "ags/engine/debugging/debug_log.h"
#include "ags/engine/debugging/debugger.h"
#include "ags/engine/main/main.h"
#include "ags/shared/ac/sprite_cache.h"
#include "ags/shared/gfx/bitmap.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/engine/gfx/graphics_driver.h"
#include "ags/engine/main/graphics_mode.h"
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index f529de8d7fa..560b3920525 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -62,7 +62,7 @@
#include "ags/engine/platform/base/ags_platform_driver.h"
#include "ags/plugins/ags_plugin.h"
#include "ags/plugins/plugin_engine.h"
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/engine/script/script.h"
#include "ags/engine/script/script_runtime.h"
#include "ags/shared/ac/sprite_cache.h"
diff --git a/engines/ags/engine/debugging/debug.cpp b/engines/ags/engine/debugging/debug.cpp
index ca2981a969d..4a090cb6398 100644
--- a/engines/ags/engine/debugging/debug.cpp
+++ b/engines/ags/engine/debugging/debug.cpp
@@ -48,8 +48,8 @@
#include "ags/engine/platform/base/sys_main.h"
#include "ags/plugins/plugin_engine.h"
#include "ags/engine/script/script.h"
-#include "ags/shared/script/script_common.h"
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_internal.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/shared/util/path.h"
#include "ags/shared/util/string_utils.h"
#include "ags/shared/util/text_stream_writer.h"
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index 10d6b506b8a..22e992c495e 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -49,7 +49,7 @@
#include "ags/engine/media/audio/audio_system.h"
#include "ags/engine/platform/base/ags_platform_driver.h"
#include "ags/plugins/plugin_engine.h"
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/engine/script/exports.h"
#include "ags/engine/script/script.h"
#include "ags/engine/script/script_runtime.h"
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index 0eb59d36cb7..3f64117102d 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -57,7 +57,7 @@
#include "ags/plugins/ags_plugin.h"
#include "ags/plugins/plugin_engine.h"
#include "ags/engine/script/script.h"
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/shared/util/aligned_stream.h"
#include "ags/shared/util/file.h"
#include "ags/shared/util/stream.h"
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index ee5fe72990b..f110d06823e 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -54,7 +54,7 @@
#include "ags/shared/gui/gui_textbox.h"
#include "ags/plugins/ags_plugin.h"
#include "ags/plugins/plugin_engine.h"
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/engine/script/script.h"
#include "ags/shared/util/file_stream.h" // TODO: needed only because plugins expect file handle
#include "ags/engine/media/audio/audio_system.h"
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index 3ceab96aaad..c0a45b6d5dc 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -52,7 +52,7 @@
#include "ags/plugins/ags_plugin.h"
#include "ags/plugins/plugin_engine.h"
#include "ags/engine/script/script.h"
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/shared/util/aligned_stream.h"
#include "ags/shared/util/string_utils.h"
diff --git a/engines/ags/engine/main/game_file.cpp b/engines/ags/engine/main/game_file.cpp
index ef2e6d12a18..5c9b2ae8dc7 100644
--- a/engines/ags/engine/main/game_file.cpp
+++ b/engines/ags/engine/main/game_file.cpp
@@ -45,7 +45,7 @@
#include "ags/shared/gui/gui_label.h"
#include "ags/engine/main/main.h"
#include "ags/engine/platform/base/ags_platform_driver.h"
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/engine/script/script.h"
#include "ags/shared/util/aligned_stream.h"
#include "ags/shared/util/stream.h"
diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index 640b06efae2..d4f8544025c 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -24,11 +24,10 @@
#include "ags/engine/ac/dynobj/cc_dynamic_array.h"
#include "ags/engine/ac/dynobj/managed_object_pool.h"
#include "ags/shared/gui/gui_defines.h"
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/engine/script/cc_instance.h"
#include "ags/engine/debugging/debug_log.h"
#include "ags/shared/debugging/out.h"
-#include "ags/shared/script/cc_options.h"
#include "ags/engine/script/script.h"
#include "ags/engine/script/script_runtime.h"
#include "ags/engine/script/system_imports.h"
diff --git a/engines/ags/engine/script/cc_instance.h b/engines/ags/engine/script/cc_instance.h
index 8b468f59e34..423bef9f738 100644
--- a/engines/ags/engine/script/cc_instance.h
+++ b/engines/ags/engine/script/cc_instance.h
@@ -24,7 +24,7 @@
#include "ags/lib/std/memory.h"
#include "ags/lib/std/map.h"
-#include "ags/shared/script/script_common.h"
+#include "ags/shared/script/cc_internal.h"
#include "ags/shared/script/cc_script.h" // ccScript
#include "ags/engine/script/non_blocking_script_function.h"
#include "ags/shared/util/string.h"
@@ -48,9 +48,6 @@ using namespace AGS;
#define INSTANCE_ID_MASK 0x00000000000000ffLL
#define INSTANCE_ID_REMOVEMASK 0x0000000000ffffffLL
-struct ccInstance;
-struct ScriptImport;
-
struct ScriptInstruction {
ScriptInstruction() {
Code = 0;
@@ -100,7 +97,6 @@ struct ScriptPosition {
// Running instance of the script
struct ccInstance {
public:
- // TODO: change to std:: if moved to C++11
typedef std::unordered_map<int32_t, ScriptVariable> ScVarMap;
typedef std::shared_ptr<ScVarMap> PScVarMap;
public:
diff --git a/engines/ags/engine/script/runtime_script_value.cpp b/engines/ags/engine/script/runtime_script_value.cpp
index dd83770d6be..7554530693a 100644
--- a/engines/ags/engine/script/runtime_script_value.cpp
+++ b/engines/ags/engine/script/runtime_script_value.cpp
@@ -19,14 +19,12 @@
*
*/
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/engine/script/runtime_script_value.h"
#include "ags/engine/ac/dynobj/cc_dynamic_object.h"
#include "ags/engine/ac/statobj/static_object.h"
#include "ags/shared/util/memory.h"
-//include <string.h> // for memcpy()
-
namespace AGS3 {
using namespace AGS::Shared;
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index 409fd59405b..d243876cb47 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -41,8 +41,7 @@
#include "ags/engine/ac/mouse.h"
#include "ags/engine/ac/room.h"
#include "ags/engine/ac/room_object.h"
-#include "ags/shared/script/cc_error.h"
-#include "ags/shared/script/cc_options.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/engine/debugging/debugger.h"
#include "ags/engine/debugging/debug_log.h"
#include "ags/engine/main/game_run.h"
diff --git a/engines/ags/engine/script/script_api.cpp b/engines/ags/engine/script/script_api.cpp
index 2b9e21a7ea3..5943b5f351e 100644
--- a/engines/ags/engine/script/script_api.cpp
+++ b/engines/ags/engine/script/script_api.cpp
@@ -20,7 +20,7 @@
*/
#include "ags/shared/ac/game_version.h"
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/engine/script/runtime_script_value.h"
#include "ags/engine/script/script_api.h"
#include "ags/shared/util/math.h"
diff --git a/engines/ags/engine/script/script_engine.cpp b/engines/ags/engine/script/script_engine.cpp
index f7c31a77d54..92478a37643 100644
--- a/engines/ags/engine/script/script_engine.cpp
+++ b/engines/ags/engine/script/script_engine.cpp
@@ -32,7 +32,7 @@
#include "ags/lib/std/utility.h"
#include "ags/engine/script/cc_instance.h"
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/shared/util/file.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
diff --git a/engines/ags/engine/script/script_runtime.cpp b/engines/ags/engine/script/script_runtime.cpp
index 292cd27d63a..668bc788caf 100644
--- a/engines/ags/engine/script/script_runtime.cpp
+++ b/engines/ags/engine/script/script_runtime.cpp
@@ -33,15 +33,11 @@
//
//=============================================================================
-#include "ags/engine/script/script_runtime.h"
-#include "ags/shared/script/script_common.h"
-#include "ags/shared/script/cc_error.h"
-#include "ags/shared/script/cc_options.h"
#include "ags/engine/ac/dynobj/cc_dynamic_array.h"
-#include "ags/engine/script/system_imports.h"
#include "ags/engine/ac/statobj/static_object.h"
-#include "ags/plugins/ags_plugin.h"
-#include "ags/plugins/plugin_base.h"
+#include "ags/shared/script/cc_common.h"
+#include "ags/engine/script/system_imports.h"
+#include "ags/engine/script/script_runtime.h"
#include "ags/globals.h"
namespace AGS3 {
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index d4da8007e60..ed1c82d30da 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -36,7 +36,7 @@
#include "ags/shared/gui/gui_listbox.h"
#include "ags/shared/gui/gui_slider.h"
#include "ags/shared/gui/gui_textbox.h"
-#include "ags/shared/script/cc_options.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/shared/util/directory.h"
#include "ags/engine/ac/draw.h"
#include "ags/engine/ac/draw_software.h"
diff --git a/engines/ags/module.mk b/engines/ags/module.mk
index 62404edf8d9..50ba7cc75c1 100644
--- a/engines/ags/module.mk
+++ b/engines/ags/module.mk
@@ -68,8 +68,7 @@ MODULE_OBJS = \
shared/gui/gui_object.o \
shared/gui/gui_slider.o \
shared/gui/gui_textbox.o \
- shared/script/cc_error.o \
- shared/script/cc_options.o \
+ shared/script/cc_common.o \
shared/script/cc_script.o \
shared/util/aligned_stream.o \
shared/util/buffered_stream.o \
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index 9604a2c5363..841224736b8 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -32,7 +32,7 @@
#include "ags/shared/game/main_game_file.h"
#include "ags/shared/font/fonts.h"
#include "ags/shared/gui/gui_main.h"
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/shared/util/aligned_stream.h"
#include "ags/shared/util/data_ext.h"
#include "ags/shared/util/path.h"
diff --git a/engines/ags/shared/game/room_file.cpp b/engines/ags/shared/game/room_file.cpp
index 5569bd0dfd5..e636d839c11 100644
--- a/engines/ags/shared/game/room_file.cpp
+++ b/engines/ags/shared/game/room_file.cpp
@@ -29,7 +29,7 @@
#include "ags/shared/game/room_file.h"
#include "ags/shared/game/room_struct.h"
#include "ags/shared/gfx/bitmap.h"
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/shared/script/cc_script.h"
#include "ags/shared/util/compress.h"
#include "ags/shared/util/data_ext.h"
diff --git a/engines/ags/shared/script/cc_error.cpp b/engines/ags/shared/script/cc_common.cpp
similarity index 88%
rename from engines/ags/shared/script/cc_error.cpp
rename to engines/ags/shared/script/cc_common.cpp
index 83e5ad7e5e2..9216ea1e5a9 100644
--- a/engines/ags/shared/script/cc_error.cpp
+++ b/engines/ags/shared/script/cc_common.cpp
@@ -20,7 +20,7 @@
*/
#include "ags/lib/std/utility.h"
-#include "ags/shared/script/script_common.h" // current_line
+#include "ags/shared/script/cc_common.h"
#include "ags/shared/util/string.h"
#include "ags/globals.h"
@@ -28,6 +28,20 @@ namespace AGS3 {
using namespace AGS::Shared;
+void ccSetOption(int optbit, int onoroff) {
+ if (onoroff)
+ _G(ccCompOptions) |= optbit;
+ else
+ _G(ccCompOptions) &= ~optbit;
+}
+
+int ccGetOption(int optbit) {
+ if (_G(ccCompOptions) & optbit)
+ return 1;
+
+ return 0;
+}
+
// Returns full script error message and callstack (if possible)
extern std::pair<String, String> cc_error_at_line(const char *error_msg);
// Returns script error message without location or callstack
diff --git a/engines/ags/shared/script/cc_options.h b/engines/ags/shared/script/cc_common.h
similarity index 85%
rename from engines/ags/shared/script/cc_options.h
rename to engines/ags/shared/script/cc_common.h
index 82e728c21d8..c282c5e5a4f 100644
--- a/engines/ags/shared/script/cc_options.h
+++ b/engines/ags/shared/script/cc_common.h
@@ -19,8 +19,12 @@
*
*/
-#ifndef AGS_SHARED_SCRIPT_CC_OPTIONS_H
-#define AGS_SHARED_SCRIPT_CC_OPTIONS_H
+// Script options and error reporting.
+
+#ifndef AGS_SHARED_SCRIPT_CC_COMMON_H
+#define AGS_SHARED_SCRIPT_CC_COMMON_H
+
+#include "ags/shared/util/string.h"
namespace AGS3 {
@@ -32,10 +36,15 @@ namespace AGS3 {
#define SCOPT_NOIMPORTOVERRIDE 0x20 // do not allow an import to be re-declared
#define SCOPT_LEFTTORIGHT 0x40 // left-to-right operator precedance
#define SCOPT_OLDSTRINGS 0x80 // allow old-style strings
+#define SCOPT_UTF8 0x100 // UTF-8 text mode
extern void ccSetOption(int, int);
extern int ccGetOption(int);
+// error reporting
+
+extern void cc_error(const char *, ...);
+
} // namespace AGS3
#endif
diff --git a/engines/ags/shared/script/cc_error.h b/engines/ags/shared/script/cc_error.h
deleted file mode 100644
index 71db6d8956a..00000000000
--- a/engines/ags/shared/script/cc_error.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* 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_SHARED_SCRIPT_CC_ERROR_H
-#define AGS_SHARED_SCRIPT_CC_ERROR_H
-
-#include "ags/shared/util/string.h"
-
-namespace AGS3 {
-
-extern void cc_error(const char *, ...);
-
-} // namespace AGS3
-
-#endif
diff --git a/engines/ags/shared/script/script_common.h b/engines/ags/shared/script/cc_internal.h
similarity index 98%
rename from engines/ags/shared/script/script_common.h
rename to engines/ags/shared/script/cc_internal.h
index 966c9445e3e..cb5e395b3c0 100644
--- a/engines/ags/shared/script/script_common.h
+++ b/engines/ags/shared/script/cc_internal.h
@@ -19,8 +19,8 @@
*
*/
-#ifndef AGS_SHARED_SCRIPT_SCRIPT_COMMON_H
-#define AGS_SHARED_SCRIPT_SCRIPT_COMMON_H
+#ifndef AGS_SHARED_SCRIPT_CC_INTERNAL_H
+#define AGS_SHARED_SCRIPT_CC_INTERNAL_H
namespace AGS3 {
diff --git a/engines/ags/shared/script/cc_options.cpp b/engines/ags/shared/script/cc_options.cpp
deleted file mode 100644
index e0005e11062..00000000000
--- a/engines/ags/shared/script/cc_options.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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/shared/script/cc_options.h"
-#include "ags/globals.h"
-
-namespace AGS3 {
-
-void ccSetOption(int optbit, int onoroff) {
- if (onoroff)
- _G(ccCompOptions) |= optbit;
- else
- _G(ccCompOptions) &= ~optbit;
-}
-
-int ccGetOption(int optbit) {
- if (_G(ccCompOptions) & optbit)
- return 1;
-
- return 0;
-}
-
-} // namespace AGS3
diff --git a/engines/ags/shared/script/cc_script.cpp b/engines/ags/shared/script/cc_script.cpp
index 07673348930..c33ce46626b 100644
--- a/engines/ags/shared/script/cc_script.cpp
+++ b/engines/ags/shared/script/cc_script.cpp
@@ -19,9 +19,9 @@
*
*/
-#include "ags/shared/script/cc_error.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/shared/script/cc_script.h"
-#include "ags/shared/script/script_common.h"
+#include "ags/shared/script/cc_internal.h"
#include "ags/shared/util/stream.h"
#include "ags/shared/util/string_compat.h"
#include "ags/globals.h"
Commit: 16d0d897872d4f742809a669d2ca266877e6a532
https://github.com/scummvm/scummvm/commit/16d0d897872d4f742809a669d2ca266877e6a532
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:07-07:00
Commit Message:
AGS: Grouped ccError variables in a struct
>From upstream 48ef387226e4d420dc62d0a0b204cf4cd89a1139
Changed paths:
engines/ags/engine/ac/event.cpp
engines/ags/engine/ac/room.cpp
engines/ags/engine/debugging/debug.cpp
engines/ags/engine/game/game_init.cpp
engines/ags/engine/game/savegame.cpp
engines/ags/engine/game/savegame_components.cpp
engines/ags/engine/game/savegame_v321.cpp
engines/ags/engine/main/game_file.cpp
engines/ags/engine/script/cc_instance.cpp
engines/ags/engine/script/script.cpp
engines/ags/globals.cpp
engines/ags/globals.h
engines/ags/shared/game/main_game_file.cpp
engines/ags/shared/game/room_file.cpp
engines/ags/shared/script/cc_common.cpp
engines/ags/shared/script/cc_common.h
diff --git a/engines/ags/engine/ac/event.cpp b/engines/ags/engine/ac/event.cpp
index fddd41b67e7..32049642c0b 100644
--- a/engines/ags/engine/ac/event.cpp
+++ b/engines/ags/engine/ac/event.cpp
@@ -133,7 +133,7 @@ void force_event(int evtyp, int ev1, int ev2, int ev3) {
void process_event(const EventHappened *evp) {
RuntimeScriptValue rval_null;
if (evp->type == EV_TEXTSCRIPT) {
- _G(ccError) = 0;
+ cc_clear_error();
RuntimeScriptValue params[2]{ evp->data2, evp->data3 };
if (evp->data3 > -1000)
QueueScriptFunction(kScInstGame, _G(tsnames)[evp->data1], 2, params);
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 560b3920525..52d39b34c24 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -406,7 +406,7 @@ HError LoadRoomScript(RoomStruct *room, int newnum) {
if (!script)
return new Error(String::FromFormat(
"Failed to load a script module: %s", filename.GetCStr()),
- _G(ccErrorString));
+ cc_get_error().ErrorString);
room->CompiledScript = script;
}
return HError::None();
@@ -989,22 +989,22 @@ void check_new_room() {
}
void compile_room_script() {
- _G(ccError) = 0;
+ cc_clear_error();
_G(roominst) = ccInstance::CreateFromScript(_GP(thisroom).CompiledScript);
- if ((_G(ccError) != 0) || (_G(roominst) == nullptr)) {
- quitprintf("Unable to create local script:\n%s", _G(ccErrorString).GetCStr());
+ if (cc_has_error() || (_G(roominst) == nullptr)) {
+ quitprintf("Unable to create local script:\n%s", cc_get_error().ErrorString.GetCStr());
}
if (!_G(roominst)->ResolveScriptImports(_G(roominst)->instanceof.get()))
- quitprintf("Unable to resolve imports in room script:\n%s", _G(ccErrorString).GetCStr());
+ quitprintf("Unable to resolve imports in room script:\n%s", cc_get_error().ErrorString.GetCStr());
if (!_G(roominst)->ResolveImportFixups(_G(roominst)->instanceof.get()))
- quitprintf("Unable to resolve import fixups in room script:\n%s", _G(ccErrorString).GetCStr());
+ quitprintf("Unable to resolve import fixups in room script:\n%s", cc_get_error().ErrorString.GetCStr());
_G(roominstFork) = _G(roominst)->Fork();
if (_G(roominstFork) == nullptr)
- quitprintf("Unable to create forked room instance:\n%s", _G(ccErrorString).GetCStr());
+ quitprintf("Unable to create forked room instance:\n%s", cc_get_error().ErrorString.GetCStr());
_GP(repExecAlways).roomHasFunction = true;
_GP(lateRepExecAlways).roomHasFunction = true;
diff --git a/engines/ags/engine/debugging/debug.cpp b/engines/ags/engine/debugging/debug.cpp
index 4a090cb6398..9b9076ac584 100644
--- a/engines/ags/engine/debugging/debug.cpp
+++ b/engines/ags/engine/debugging/debug.cpp
@@ -322,7 +322,7 @@ String get_cur_script(int numberOfLinesOfCallStack) {
if (sci)
callstack = sci->GetCallStack(numberOfLinesOfCallStack);
if (callstack.IsEmpty())
- callstack = _G(ccErrorCallStack);
+ callstack = cc_get_error().CallStack;
return callstack;
}
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index 22e992c495e..01aa82f49ae 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -444,7 +444,7 @@ HGameInitError InitGameState(const LoadedGameEntities &ents, GameDataVersion dat
_GP(scriptModules) = ents.ScriptModules;
AllocScriptModules();
if (create_global_script())
- return new GameInitError(kGameInitErr_ScriptLinkFailed, _G(ccErrorString));
+ return new GameInitError(kGameInitErr_ScriptLinkFailed, cc_get_error().ErrorString);
return HGameInitError::None();
}
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index 3f64117102d..e05bf43b694 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -457,7 +457,7 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
if (create_global_script()) {
return new SavegameError(kSvgErr_GameObjectInitFailed,
- String::FromFormat("Unable to recreate global script: %s", _G(ccErrorString).GetCStr()));
+ String::FromFormat("Unable to recreate global script: %s", cc_get_error().ErrorString.GetCStr()));
}
// read the global data into the newly created script
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index f110d06823e..248511f6079 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -989,7 +989,7 @@ HSaveError WriteManagedPool(Stream *out) {
HSaveError ReadManagedPool(Stream *in, int32_t cmp_ver, const PreservedParams & /*pp*/, RestoredData & /*r_data*/) {
if (ccUnserializeAllObjects(in, &_GP(ccUnserializer))) {
return new SavegameError(kSvgErr_GameObjectInitFailed,
- String::FromFormat("Managed pool deserialization failed: %s", _G(ccErrorString).GetCStr()));
+ String::FromFormat("Managed pool deserialization failed: %s", cc_get_error().ErrorString.GetCStr()));
}
return HSaveError::None();
}
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index c0a45b6d5dc..18a0e73622a 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -493,7 +493,7 @@ HSaveError restore_save_data_v321(Stream *in, const PreservedParams &pp, Restore
if (ccUnserializeAllObjects(in, &_GP(ccUnserializer))) {
return new SavegameError(kSvgErr_GameObjectInitFailed,
- String::FromFormat("Managed pool deserialization failed: %s.", _G(ccErrorString).GetCStr()));
+ String::FromFormat("Managed pool deserialization failed: %s.", cc_get_error().ErrorString.GetCStr()));
}
// preserve legacy music type setting
diff --git a/engines/ags/engine/main/game_file.cpp b/engines/ags/engine/main/game_file.cpp
index 5c9b2ae8dc7..a61aea73b05 100644
--- a/engines/ags/engine/main/game_file.cpp
+++ b/engines/ags/engine/main/game_file.cpp
@@ -119,7 +119,7 @@ HError preload_game_data() {
static inline HError MakeScriptLoadError(const char *name) {
return new Error(String::FromFormat(
"Failed to load a script module: %s", name),
- _G(ccErrorString));
+ cc_get_error().ErrorString);
}
// Looks up for the game scripts available as separate assets.
diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index d4f8544025c..d80377b54e5 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -262,7 +262,7 @@ void ccInstance::AbortAndDestroy() {
}
int ccInstance::CallScriptFunction(const char *funcname, int32_t numargs, const RuntimeScriptValue *params) {
- _G(ccError) = 0;
+ cc_clear_error();
_G(currentline) = 0;
if (numargs > 0 && !params) {
@@ -367,7 +367,7 @@ int ccInstance::CallScriptFunction(const char *funcname, int32_t numargs, const
cc_error("stack pointer was not zero at completion of script");
return -5;
}
- return _G(ccError);
+ return cc_has_error();
}
// Macros to maintain the call stack
@@ -532,7 +532,7 @@ int ccInstance::Run(int32_t curpc) {
registers[SREG_SP].RValue++;
} else {
PushDataToStack(arg2.IValue);
- if (_G(ccError)) {
+ if (cc_has_error()) {
return -1;
}
}
@@ -553,7 +553,7 @@ int ccInstance::Run(int32_t curpc) {
// This is practically LOADSPOFFS
reg1 = GetStackPtrOffsetRw(arg2.IValue);
}
- if (_G(ccError)) {
+ if (cc_has_error()) {
return -1;
}
} else {
@@ -614,7 +614,7 @@ int ccInstance::Run(int32_t curpc) {
break;
case SCMD_LOADSPOFFS:
registers[SREG_MAR] = GetStackPtrOffsetRw(arg1.IValue);
- if (_G(ccError)) {
+ if (cc_has_error()) {
return -1;
}
break;
@@ -693,9 +693,6 @@ int ccInstance::Run(int32_t curpc) {
ASSERT_STACK_SPACE_AVAILABLE(1);
PushValueToStack(RuntimeScriptValue().SetInt32(pc + codeOp.ArgCount + 1));
- if (_G(ccError)) {
- return -1;
- }
if (thisbase[curnest] == 0)
pc = reg1.IValue;
@@ -741,9 +738,6 @@ int ccInstance::Run(int32_t curpc) {
// Push reg[arg1] value to the stack
ASSERT_STACK_SPACE_AVAILABLE(1);
PushValueToStack(reg1);
- if (_G(ccError)) {
- return -1;
- }
break;
case SCMD_POPREG:
ASSERT_STACK_SIZE(1);
@@ -796,7 +790,7 @@ int ccInstance::Run(int32_t curpc) {
// 64 bit: Handles are always 32 bit values. They are not C pointer.
case SCMD_MEMREADPTR: {
- _G(ccError) = 0;
+ cc_clear_error();
int32_t handle = registers[SREG_MAR].ReadInt32();
void *object;
@@ -809,7 +803,7 @@ int ccInstance::Run(int32_t curpc) {
}
// if error occurred, cc_error will have been set
- if (_G(ccError))
+ if (cc_has_error())
return -1;
break;
}
@@ -925,7 +919,7 @@ int ccInstance::Run(int32_t curpc) {
// 0, so that the cc_run_code returns
RuntimeScriptValue oldstack = registers[SREG_SP];
PushValueToStack(RuntimeScriptValue().SetInt32(0));
- if (_G(ccError)) {
+ if (cc_has_error()) {
return -1;
}
@@ -1021,7 +1015,7 @@ int ccInstance::Run(int32_t curpc) {
cc_error("invalid pointer type for function call: %d", reg1.Type);
}
- if (_G(ccError) || _G(abort_engine)) {
+ if (cc_has_error() || _G(abort_engine)) {
return -1;
}
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index d243876cb47..3a89de31303 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -302,22 +302,21 @@ static bool DoRunScriptFuncCantBlock(ccInstance *sci, NonBlockingScriptFunction
}
// this might be nested, so don't disrupt blocked scripts
- _G(ccErrorString) = "";
- _G(ccError) = 0;
+ cc_clear_error();
_G(no_blocking_functions)--;
return (hasTheFunc);
}
static int PrepareTextScript(ccInstance *sci, const char **tsname) {
- _G(ccError) = 0;
+ cc_clear_error();
// FIXME: try to make it so this function is not called with NULL sci
if (sci == nullptr) return -1;
if (sci->GetSymbolAddress(tsname[0]).IsNull()) {
- _G(ccErrorString) = "no such function in script";
+ cc_error("no such function in script");
return -2;
}
if (sci->IsBeingRun()) {
- _G(ccErrorString) = "script is already in execution";
+ cc_error("script is already in execution");
return -3;
}
_G(scripts)[_G(num_scripts)].init();
@@ -339,36 +338,21 @@ static int PrepareTextScript(ccInstance *sci, const char **tsname) {
tsname[0] = &scfunctionname[0];
update_script_mouse_coords();
_G(inside_script)++;
- // aborted_ip=0;
- // abort_executor=0;
return 0;
}
int RunScriptFunction(ccInstance *sci, const char *tsname, size_t numParam, const RuntimeScriptValue *params) {
int oldRestoreCount = _G(gameHasBeenRestored);
- // First, save the current ccError state
- // This is necessary because we might be attempting
- // to run Script B, while Script A is still running in the
- // background.
- // If CallInstance here has an error, it would otherwise
- // also abort Script A because ccError is a global variable.
- int cachedCcError = _G(ccError);
- _G(ccError) = 0;
+ cc_clear_error();
int toret = PrepareTextScript(sci, &tsname);
if (toret) {
- _G(ccError) = cachedCcError;
return -18;
}
- // Clear the error message
- _G(ccErrorString) = "";
-
+ cc_clear_error();
toret = _G(curscript)->inst->CallScriptFunction(tsname, numParam, params);
- if (_G(abort_engine))
- return -1;
-
// 100 is if Aborted (eg. because we are LoadAGSGame'ing)
if ((toret != 0) && (toret != -2) && (toret != 100)) {
quit_with_script_error(tsname);
@@ -383,9 +367,6 @@ int RunScriptFunction(ccInstance *sci, const char *tsname, size_t numParam, cons
_G(post_script_cleanup_stack)--;
- // restore cached error state
- _G(ccError) = cachedCcError;
-
// if the game has been restored, ensure that any further scripts are not run
if ((oldRestoreCount != _G(gameHasBeenRestored)) && (_G(eventClaimed) == EVENT_INPROGRESS))
_G(eventClaimed) = EVENT_CLAIMED;
@@ -408,7 +389,7 @@ int RunScriptFunctionInRoom(const char *tsname, size_t param_count, const Runtim
// If it's a obligatory room event, and return code means missing function - error
if (strict_room_event && (toret == -18))
quitprintf("RunScriptFunction: error %d (%s) trying to run '%s' (Room %d)",
- toret, _G(ccErrorString).GetCStr(), tsname, _G(displayed_room));
+ toret, cc_get_error().ErrorString.GetCStr(), tsname, _G(displayed_room));
return toret;
}
@@ -487,7 +468,8 @@ char *make_ts_func_name(const char *base, int iii, int subd) {
void post_script_cleanup() {
// should do any post-script stuff here, like go to new room
- if (_G(ccError)) quit(_G(ccErrorString));
+ if (cc_has_error())
+ quit(cc_get_error().ErrorString);
ExecutingScript copyof = _G(scripts)[_G(num_scripts) - 1];
if (_G(scripts)[_G(num_scripts) - 1].forked)
delete _G(scripts)[_G(num_scripts) - 1].inst;
@@ -577,10 +559,12 @@ void quit_with_script_error(const char *functionName) {
// TODO: clean up the error reporting logic. Now engine will append call
// stack info in quit_check_for_error_state() but only in case of explicit
// script error ("!" type), and not in other case.
- if (_G(ccErrorIsUserError))
- quitprintf("!Error running function '%s':\n%s", functionName, _G(ccErrorString).GetCStr());
+ const auto &error = cc_get_error();
+ if (error.IsUserError)
+ quitprintf("!Error running function '%s':\n%s", functionName, error.ErrorString.GetCStr());
else
- quitprintf("Error running function '%s':\n%s\n\n%s", functionName, _G(ccErrorString).GetCStr(), get_cur_script(5).GetCStr());
+ quitprintf("Error running function '%s':\n%s\n\n%s", functionName,
+ error.ErrorString.GetCStr(), get_cur_script(5).GetCStr());
}
int get_nivalue(InteractionCommandList *nic, int idx, int parm) {
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index ed1c82d30da..cee427f6d65 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -141,6 +141,9 @@ Globals::Globals() {
// cc_dynamicarray.cpp globals
_globalDynamicArray = new CCDynamicArray();
+ // cc_common globals
+ _ccError = new ScriptError();
+
// csc_dialog.cpp globals
_vobjs = new NewControl *[MAXCONTROLS];
_oswi = new OnScreenWindow[MAXSCREENWINDOWS];
@@ -407,6 +410,9 @@ Globals::~Globals() {
// cc_dynamic_array.cpp globals
delete _globalDynamicArray;
+ // cc_common.cpp globals
+ delete _ccError;
+
// cscdialog.cpp globals
delete[] _vobjs;
delete[] _oswi;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index f14d33d7fbe..a5aa0b1ee7a 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -162,6 +162,7 @@ struct ScriptAudioChannel;
struct ScriptDialog;
struct ScriptDialogOptionsRendering;
struct ScriptDrawingSurface;
+struct ScriptError;
struct ScriptGUI;
struct ScriptHotspot;
struct ScriptInvItem;
@@ -350,17 +351,11 @@ public:
/**@}*/
/**
- * @defgroup agscc_errorglobals cc_error globals
+ * @defgroup agscc_commonglobals cc_common globals
* @ingroup agsglobals
* @{
*/
-
- int _ccError = 0;
- int _ccErrorLine = 0;
- String _ccErrorString;
- String _ccErrorCallStack;
- bool _ccErrorIsUserError = false;
- const char *_ccCurScriptName = "";
+ ScriptError *_ccError;
/**@}*/
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index 841224736b8..7c4932c4970 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -220,7 +220,7 @@ HGameFileError ReadDialogScript(PScript &dialog_script, Stream *in, GameDataVers
if (data_ver > kGameVersion_310) { // 3.1.1+ dialog script
dialog_script.reset(ccScript::CreateFromStream(in));
if (dialog_script == nullptr)
- return new MainGameFileError(kMGFErr_CreateDialogScriptFailed, _G(ccErrorString));
+ return new MainGameFileError(kMGFErr_CreateDialogScriptFailed, cc_get_error().ErrorString);
} else { // 2.x and < 3.1.1 dialog
dialog_script.reset();
}
@@ -234,7 +234,7 @@ HGameFileError ReadScriptModules(std::vector<PScript> &sc_mods, Stream *in, Game
for (int i = 0; i < count; ++i) {
sc_mods[i].reset(ccScript::CreateFromStream(in));
if (sc_mods[i] == nullptr)
- return new MainGameFileError(kMGFErr_CreateScriptModuleFailed, _G(ccErrorString));
+ return new MainGameFileError(kMGFErr_CreateScriptModuleFailed, cc_get_error().ErrorString);
}
} else {
sc_mods.resize(0);
@@ -778,7 +778,7 @@ HGameFileError ReadGameData(LoadedGameEntities &ents, Stream *in, GameDataVersio
if (game.load_compiled_script) {
ents.GlobalScript.reset(ccScript::CreateFromStream(in));
if (!ents.GlobalScript)
- return new MainGameFileError(kMGFErr_CreateGlobalScriptFailed, _G(ccErrorString));
+ return new MainGameFileError(kMGFErr_CreateGlobalScriptFailed, cc_get_error().ErrorString);
err = ReadDialogScript(ents.DialogScript, in, data_ver);
if (!err)
return err;
diff --git a/engines/ags/shared/game/room_file.cpp b/engines/ags/shared/game/room_file.cpp
index e636d839c11..0db9e4bd203 100644
--- a/engines/ags/shared/game/room_file.cpp
+++ b/engines/ags/shared/game/room_file.cpp
@@ -332,7 +332,7 @@ HError ReadScriptBlock(char *&buf, Stream *in, RoomFileVersion /*data_ver*/) {
HError ReadCompSc3Block(RoomStruct *room, Stream *in, RoomFileVersion /*data_ver*/) {
room->CompiledScript.reset(ccScript::CreateFromStream(in));
if (room->CompiledScript == nullptr)
- return new RoomFileError(kRoomFileErr_ScriptLoadFailed, _G(ccErrorString));
+ return new RoomFileError(kRoomFileErr_ScriptLoadFailed, cc_get_error().ErrorString);
return HError::None();
}
diff --git a/engines/ags/shared/script/cc_common.cpp b/engines/ags/shared/script/cc_common.cpp
index 9216ea1e5a9..054c8b20a32 100644
--- a/engines/ags/shared/script/cc_common.cpp
+++ b/engines/ags/shared/script/cc_common.cpp
@@ -47,10 +47,22 @@ extern std::pair<String, String> cc_error_at_line(const char *error_msg);
// Returns script error message without location or callstack
extern String cc_error_without_line(const char *error_msg);
+void cc_clear_error() {
+ _GP(ccError) = ScriptError();
+}
+
+bool cc_has_error() {
+ return _GP(ccError).HasError;
+}
+
+const ScriptError &cc_get_error() {
+ return _GP(ccError);
+}
+
void cc_error(const char *descr, ...) {
- _G(ccErrorIsUserError) = false;
+ _GP(ccError).IsUserError = false;
if (descr[0] == '!') {
- _G(ccErrorIsUserError) = true;
+ _GP(ccError).IsUserError = true;
descr++;
}
@@ -62,15 +74,15 @@ void cc_error(const char *descr, ...) {
if (_G(currentline) > 0) {
// [IKM] Implementation is project-specific
std::pair<String, String> errinfo = cc_error_at_line(displbuf.GetCStr());
- _G(ccErrorString) = errinfo.first;
- _G(ccErrorCallStack) = errinfo.second;
+ _GP(ccError).ErrorString = errinfo.first;
+ _GP(ccError).CallStack = errinfo.second;
} else {
- _G(ccErrorString) = cc_error_without_line(displbuf.GetCStr());
- _G(ccErrorCallStack) = "";
+ _GP(ccError).ErrorString = cc_error_without_line(displbuf.GetCStr());
+ _GP(ccError).CallStack = "";
}
- _G(ccError) = 1;
- _G(ccErrorLine) = _G(currentline);
+ _GP(ccError).HasError = 1;
+ _GP(ccError).Line = _G(currentline);
}
} // namespace AGS3
diff --git a/engines/ags/shared/script/cc_common.h b/engines/ags/shared/script/cc_common.h
index c282c5e5a4f..8c0678aab04 100644
--- a/engines/ags/shared/script/cc_common.h
+++ b/engines/ags/shared/script/cc_common.h
@@ -43,7 +43,18 @@ extern int ccGetOption(int);
// error reporting
-extern void cc_error(const char *, ...);
+struct ScriptError {
+ bool HasError = false; // set if error occurs
+ bool IsUserError = false; // marks script use errors
+ AGS::Shared::String ErrorString; // description of the error
+ int Line = 0; // line number of the error
+ AGS::Shared::String CallStack; // callstack where error happened
+};
+
+void cc_clear_error();
+bool cc_has_error();
+const ScriptError &cc_get_error();
+void cc_error(const char *, ...);
} // namespace AGS3
Commit: 8e132f7b3f5d95212d0d7d4a6a63753cbce1ba75
https://github.com/scummvm/scummvm/commit/8e132f7b3f5d95212d0d7d4a6a63753cbce1ba75
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:07-07:00
Commit Message:
AGS: cc_error returns stack from all script threads
>From upstream 9e76800d668d8d0af7d47d815e6d1b781c7601f6
Changed paths:
R engines/ags/engine/script/script_engine.cpp
engines/ags/engine/ac/draw.cpp
engines/ags/engine/debugging/debug.cpp
engines/ags/engine/debugging/debugger.h
engines/ags/engine/main/quit.cpp
engines/ags/engine/script/cc_instance.cpp
engines/ags/engine/script/cc_instance.h
engines/ags/engine/script/script.cpp
engines/ags/globals.cpp
engines/ags/globals.h
engines/ags/lib/std/queue.h
engines/ags/module.mk
engines/ags/shared/script/cc_common.cpp
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index c781bfa4619..4e7910f7cc9 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1675,7 +1675,7 @@ void prepare_room_sprites() {
if (_G(walkBehindMethod) == DrawAsSeparateSprite) {
for (int wb = 1 /* 0 is "no area" */;
- (wb < MAX_WALK_BEHINDS) && (wb < _GP(walkbehindobj).size()); ++wb) {
+ (wb < MAX_WALK_BEHINDS) && (wb < (int)_GP(walkbehindobj).size()); ++wb) {
const auto &wbobj = _GP(walkbehindobj)[wb];
if (wbobj.Ddb) {
add_to_sprite_list(wbobj.Ddb, wbobj.Pos.X, wbobj.Pos.Y,
diff --git a/engines/ags/engine/debugging/debug.cpp b/engines/ags/engine/debugging/debug.cpp
index 9b9076ac584..3b0644d8c32 100644
--- a/engines/ags/engine/debugging/debug.cpp
+++ b/engines/ags/engine/debugging/debug.cpp
@@ -315,24 +315,13 @@ void debug_script_log(const char *msg, ...) {
debug_script_print_impl(full_msg, kDbgMsg_Debug);
}
-
-String get_cur_script(int numberOfLinesOfCallStack) {
- String callstack;
- ccInstance *sci = ccInstance::GetCurrentInstance();
- if (sci)
- callstack = sci->GetCallStack(numberOfLinesOfCallStack);
- if (callstack.IsEmpty())
- callstack = cc_get_error().CallStack;
- return callstack;
-}
-
struct Breakpoint {
char scriptName[80];
int lineNumber;
};
bool send_message_to_editor(const char *msg, const char *errorMsg) {
- String callStack = get_cur_script(25);
+ String callStack = cc_get_error().CallStack;
if (callStack.IsEmpty())
return false;
diff --git a/engines/ags/engine/debugging/debugger.h b/engines/ags/engine/debugging/debugger.h
index 0929797b366..60ad55026e8 100644
--- a/engines/ags/engine/debugging/debugger.h
+++ b/engines/ags/engine/debugging/debugger.h
@@ -32,8 +32,6 @@ struct ScriptPosition;
int check_for_messages_from_editor();
bool send_message_to_editor(const char *msg);
bool send_exception_to_editor(const char *qmsg);
-// Returns current script's location and callstack
-AGS::Shared::String get_cur_script(int numberOfLinesOfCallStack);
void check_debug_keys();
#define DBG_NOIFACE 1
diff --git a/engines/ags/engine/main/quit.cpp b/engines/ags/engine/main/quit.cpp
index ae73e19bd00..77a8413ad45 100644
--- a/engines/ags/engine/main/quit.cpp
+++ b/engines/ags/engine/main/quit.cpp
@@ -48,6 +48,7 @@
#include "ags/engine/platform/base/ags_platform_driver.h"
#include "ags/engine/platform/base/sys_main.h"
#include "ags/plugins/plugin_engine.h"
+#include "ags/shared/script/cc_common.h"
#include "ags/engine/media/audio/audio_system.h"
#include "ags/globals.h"
#include "ags/ags.h"
@@ -114,7 +115,7 @@ QuitReason quit_check_for_error_state(const char *&qmsg, String &alertis) {
"(ACI version %s)\n\n", _G(EngineVersion).LongString.GetCStr());
}
- alertis.Append(get_cur_script(5));
+ alertis.Append(cc_get_error().CallStack);
if (qreason != kQuit_UserAbort)
alertis.Append("\nError: ");
@@ -125,7 +126,7 @@ QuitReason quit_check_for_error_state(const char *&qmsg, String &alertis) {
qmsg++;
alertis.Format("A warning has been generated. This is not normally fatal, but you have selected "
"to treat warnings as errors.\n"
- "(ACI version %s)\n\n%s\n", _G(EngineVersion).LongString.GetCStr(), get_cur_script(5).GetCStr());
+ "(ACI version %s)\n\n%s\n", _G(EngineVersion).LongString.GetCStr(), cc_get_error().CallStack.GetCStr());
return kQuit_GameWarning;
} else {
alertis.Format("An internal error has occurred. Please note down the following information.\n"
diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index d80377b54e5..3a0217bca5e 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -157,6 +157,18 @@ const char *regnames[] = { "null", "sp", "mar", "ax", "bx", "cx", "op", "dx" };
const char *fixupnames[] = { "null", "fix_gldata", "fix_func", "fix_string", "fix_import", "fix_datadata", "fix_stack" };
+String cc_get_callstack(int max_lines) {
+ String callstack;
+ for (auto sci = _GP(InstThreads).crbegin(); sci != _GP(InstThreads).crend(); ++sci) {
+ if (callstack.IsEmpty())
+ callstack.Append("in the active script:\n");
+ else
+ callstack.Append("in the waiting script:\n");
+ callstack.Append((*sci)->GetCallStack(max_lines));
+ }
+ return callstack;
+}
+
// Function call stack is used to temporarily store
// values before passing them to script function
#define MAX_FUNC_PARAMS 20
@@ -181,7 +193,7 @@ struct FunctionCallStack {
ccInstance *ccInstance::GetCurrentInstance() {
- return _GP(InstThreads).size() > 0 ? _GP(InstThreads).top() : nullptr;
+ return _GP(InstThreads).size() > 0 ? _GP(InstThreads).back() : nullptr;
}
ccInstance *ccInstance::CreateFromScript(PScript scri) {
@@ -335,14 +347,14 @@ int ccInstance::CallScriptFunction(const char *funcname, int32_t numargs, const
}
PushValueToStack(RuntimeScriptValue().SetInt32(0)); // return address on stack
- _GP(InstThreads).push(this); // push instance thread
+ _GP(InstThreads).push_back(this); // push instance thread
runningInst = this;
int reterr = Run(startat);
// Cleanup before returning, even if error
ASSERT_STACK_SIZE(numargs);
PopValuesFromStack(numargs);
pc = 0;
- _GP(InstThreads).pop(); // pop instance thread
+ _GP(InstThreads).pop_back(); // pop instance thread
if (reterr != 0)
return reterr;
@@ -1198,7 +1210,7 @@ int ccInstance::Run(int32_t curpc) {
}
}
-String ccInstance::GetCallStack(int maxLines) {
+String ccInstance::GetCallStack(int maxLines) const {
String buffer = String::FromFormat("in \"%s\", line %d\n", runningInst->instanceof->GetSectionName(pc), line_number);
int linesDone = 0;
@@ -1212,13 +1224,13 @@ String ccInstance::GetCallStack(int maxLines) {
return buffer;
}
-void ccInstance::GetScriptPosition(ScriptPosition &script_pos) {
+void ccInstance::GetScriptPosition(ScriptPosition &script_pos) const {
script_pos.Section = runningInst->instanceof->GetSectionName(pc);
script_pos.Line = line_number;
}
// get a pointer to a variable or function exported by the script
-RuntimeScriptValue ccInstance::GetSymbolAddress(const char *symname) {
+RuntimeScriptValue ccInstance::GetSymbolAddress(const char *symname) const {
int k;
char altName[200];
snprintf(altName, sizeof(altName), "%s$", symname);
@@ -1234,7 +1246,7 @@ RuntimeScriptValue ccInstance::GetSymbolAddress(const char *symname) {
return rval_null;
}
-void ccInstance::DumpInstruction(const ScriptOperation &op) {
+void ccInstance::DumpInstruction(const ScriptOperation &op) const {
// line_num local var should be shared between all the instances
static int line_num = 0;
diff --git a/engines/ags/engine/script/cc_instance.h b/engines/ags/engine/script/cc_instance.h
index 423bef9f738..3895d68ed14 100644
--- a/engines/ags/engine/script/cc_instance.h
+++ b/engines/ags/engine/script/cc_instance.h
@@ -159,12 +159,12 @@ public:
int CallScriptFunction(const char *funcname, int32_t num_params, const RuntimeScriptValue *params);
// Get the script's execution position and callstack as human-readable text
- Shared::String GetCallStack(int maxLines);
+ Shared::String GetCallStack(int max_lines = INT_MAX) const;
// Get the script's execution position
- void GetScriptPosition(ScriptPosition &script_pos);
+ void GetScriptPosition(ScriptPosition &script_pos) const;
// Get the address of an exported symbol (function or variable) in the script
- RuntimeScriptValue GetSymbolAddress(const char *symname);
- void DumpInstruction(const ScriptOperation &op);
+ RuntimeScriptValue GetSymbolAddress(const char *symname) const;
+ void DumpInstruction(const ScriptOperation &op) const;
// Tells whether this instance is in the process of executing the byte-code
bool IsBeingRun() const;
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index 3a89de31303..19d190e4f8e 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -564,7 +564,7 @@ void quit_with_script_error(const char *functionName) {
quitprintf("!Error running function '%s':\n%s", functionName, error.ErrorString.GetCStr());
else
quitprintf("Error running function '%s':\n%s\n\n%s", functionName,
- error.ErrorString.GetCStr(), get_cur_script(5).GetCStr());
+ error.ErrorString.GetCStr(), error.CallStack.GetCStr());
}
int get_nivalue(InteractionCommandList *nic, int idx, int parm) {
diff --git a/engines/ags/engine/script/script_engine.cpp b/engines/ags/engine/script/script_engine.cpp
deleted file mode 100644
index 92478a37643..00000000000
--- a/engines/ags/engine/script/script_engine.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/* 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/>.
- *
- */
-
-//=============================================================================
-//
-// Script Editor run-time engine component (c) 1998 Chris Jones
-// script chunk format:
-// 00h 1 dword version - should be 2
-// 04h 1 dword sizeof(scriptblock)
-// 08h 1 dword number of ScriptBlocks
-// 0Ch n STRUCTs ScriptBlocks
-//
-//=============================================================================
-
-#include "ags/lib/std/utility.h"
-#include "ags/engine/script/cc_instance.h"
-#include "ags/shared/script/cc_common.h"
-#include "ags/shared/util/file.h"
-#include "ags/shared/util/stream.h"
-#include "ags/globals.h"
-
-namespace AGS3 {
-
-namespace AGS {
-namespace Shared {
-class RoomStruct;
-} // namespace Shared
-} // namespace AGS
-
-using namespace AGS::Shared;
-
-std::pair<String, String> cc_error_at_line(const char *error_msg) {
- ccInstance *sci = ccInstance::GetCurrentInstance();
- if (!sci) {
- return std::make_pair(String::FromFormat("Error (line %d): %s", _G(currentline), error_msg), String());
- } else {
- return std::make_pair(String::FromFormat("Error: %s\n", error_msg), ccInstance::GetCurrentInstance()->GetCallStack(5));
- }
-}
-
-String cc_error_without_line(const char *error_msg) {
- return String::FromFormat("Runtime error: %s", error_msg);
-}
-
-} // namespace AGS3
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index cee427f6d65..8c835dc464f 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -129,7 +129,7 @@ Globals::Globals() {
_animbuts = new std::vector<AnimatingGUIButton>();
// cc_instance.cpp globals
- _InstThreads = new std::stack<ccInstance *>();
+ _InstThreads = new std::deque<ccInstance *>();
_GlobalReturnValue = new RuntimeScriptValue();
// cc_options.cpp globals
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index a5aa0b1ee7a..a3f5a7082f5 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -25,7 +25,7 @@
#include "ags/shared/core/platform.h"
#define AGS_PLATFORM_DEFINES_PSP_VARS (AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID)
-#include "ags/lib/std/stack.h"
+#include "ags/lib/std/queue.h"
#include "ags/shared/ac/game_version.h"
#include "ags/shared/util/stdio_compat.h"
#include "ags/shared/util/string.h"
@@ -369,7 +369,7 @@ public:
// In AGS currently only one thread is running, others are waiting in the queue.
// An example situation is repeatedly_execute_always callback running while
// another instance is waiting at the blocking action or Wait().
- std::stack<ccInstance *> *_InstThreads;
+ std::deque<ccInstance *> *_InstThreads;
// [IKM] 2012-10-21:
// NOTE: This is temporary solution (*sigh*, one of many) which allows certain
// exported functions return value as a RuntimeScriptValue object;
diff --git a/engines/ags/lib/std/queue.h b/engines/ags/lib/std/queue.h
index ead08567d02..1617c2a5b01 100644
--- a/engines/ags/lib/std/queue.h
+++ b/engines/ags/lib/std/queue.h
@@ -63,6 +63,80 @@ public:
}
};
+template<class T>
+class deque {
+private:
+ vector<T> _intern;
+public:
+ deque() = default;
+ typedef typename vector<T>::iterator iterator;
+ typedef typename const vector<T>::const_iterator const_iterator;
+ typedef typename vector<T>::reverse_iterator reverse_iterator;
+ typedef typename const vector<T>::const_reverse_iterator const_reverse_iterator;
+
+ void clear() {
+ _intern.clear();
+ }
+ void insert(const T &item) {
+ _intern.push_back(item);
+ }
+ void push_back(const T &item) {
+ _intern.push_back(item);
+ }
+ void push_front(const T &item) {
+ _intern.push_front(item);
+ }
+ void pop_back() {
+ _intern.pop_back();
+ }
+ void pop_front() {
+ _intern.remove_at(0);
+ }
+ const T &front() const {
+ return _intern.front();
+ }
+ const T &back() const {
+ return _intern.back();
+ }
+
+ void resize(size_t newSize) {
+ _intern.resize(newSize);
+ }
+
+ size_t size() const {
+ return _intern.size();
+ }
+
+ T at(size_t idx) {
+ return _intern[idx];
+ }
+
+ const_iterator cbegin() {
+ return _intern.cbegin();
+ }
+ const_iterator cend() {
+ return _intern.cend();
+ }
+ reverse_iterator rbegin() {
+ return _intern.rbegin();
+ }
+ reverse_iterator rend() {
+ return _intern.rend();
+ }
+ const_reverse_iterator rbegin() const {
+ return _intern.rbegin();
+ }
+ const_reverse_iterator rend() const {
+ return _intern.rend();
+ }
+ const_reverse_iterator crbegin() const {
+ return _intern.crbegin();
+ }
+ const_reverse_iterator crend() const {
+ return _intern.crend();
+ }
+};
+
} // namespace std
} // namespace AGS3
diff --git a/engines/ags/module.mk b/engines/ags/module.mk
index 50ba7cc75c1..13c73481072 100644
--- a/engines/ags/module.mk
+++ b/engines/ags/module.mk
@@ -279,7 +279,6 @@ MODULE_OBJS = \
engine/script/runtime_script_value.o \
engine/script/script.o \
engine/script/script_api.o \
- engine/script/script_engine.o \
engine/script/script_runtime.o \
engine/script/system_imports.o \
plugins/ags_plugin.o \
diff --git a/engines/ags/shared/script/cc_common.cpp b/engines/ags/shared/script/cc_common.cpp
index 054c8b20a32..3e7dfa97158 100644
--- a/engines/ags/shared/script/cc_common.cpp
+++ b/engines/ags/shared/script/cc_common.cpp
@@ -42,10 +42,8 @@ int ccGetOption(int optbit) {
return 0;
}
-// Returns full script error message and callstack (if possible)
-extern std::pair<String, String> cc_error_at_line(const char *error_msg);
-// Returns script error message without location or callstack
-extern String cc_error_without_line(const char *error_msg);
+// Returns current running script callstack as a human-readable text
+extern String cc_get_callstack(int max_lines = INT_MAX);
void cc_clear_error() {
_GP(ccError) = ScriptError();
@@ -71,15 +69,12 @@ void cc_error(const char *descr, ...) {
String displbuf = String::FromFormatV(descr, ap);
va_end(ap);
- if (_G(currentline) > 0) {
- // [IKM] Implementation is project-specific
- std::pair<String, String> errinfo = cc_error_at_line(displbuf.GetCStr());
- _GP(ccError).ErrorString = errinfo.first;
- _GP(ccError).CallStack = errinfo.second;
- } else {
- _GP(ccError).ErrorString = cc_error_without_line(displbuf.GetCStr());
- _GP(ccError).CallStack = "";
- }
+ String callstack = cc_get_callstack();
+ if ((_G(currentline) > 0) && callstack.IsEmpty())
+ _GP(ccError).ErrorString = String::FromFormat("Error (line %d): %s", _G(currentline), displbuf.GetCStr());
+ else
+ _GP(ccError).ErrorString = String::FromFormat("Error: %s", displbuf.GetCStr());
+ _GP(ccError).CallStack = callstack;
_GP(ccError).HasError = 1;
_GP(ccError).Line = _G(currentline);
Commit: 540a92a6c532c5b9449c97b55f19ed22d5540bb8
https://github.com/scummvm/scummvm/commit/540a92a6c532c5b9449c97b55f19ed22d5540bb8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:07-07:00
Commit Message:
AGS: Necessary fixes to build with latest changes to ccError
>From upstream 238b18e2ea0a34742d50c5d4298a06cc3077dcdd
Changed paths:
engines/ags/engine/script/script.cpp
engines/ags/shared/script/cc_common.cpp
engines/ags/shared/script/cc_common.h
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index 19d190e4f8e..3a25cb36f26 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -882,4 +882,11 @@ bool get_script_position(ScriptPosition &script_pos) {
return false;
}
+String cc_format_error(const String &message) {
+ if (_G(currentline) > 0)
+ return String::FromFormat("Error (line %d): %s", _G(currentline), message.GetCStr());
+ else
+ return String::FromFormat("Error (line unknown): %s", message.GetCStr());
+}
+
} // namespace AGS3
diff --git a/engines/ags/shared/script/cc_common.cpp b/engines/ags/shared/script/cc_common.cpp
index 3e7dfa97158..67d165376f6 100644
--- a/engines/ags/shared/script/cc_common.cpp
+++ b/engines/ags/shared/script/cc_common.cpp
@@ -69,13 +69,10 @@ void cc_error(const char *descr, ...) {
String displbuf = String::FromFormatV(descr, ap);
va_end(ap);
- String callstack = cc_get_callstack();
- if ((_G(currentline) > 0) && callstack.IsEmpty())
- _GP(ccError).ErrorString = String::FromFormat("Error (line %d): %s", _G(currentline), displbuf.GetCStr());
- else
- _GP(ccError).ErrorString = String::FromFormat("Error: %s", displbuf.GetCStr());
- _GP(ccError).CallStack = callstack;
-
+ // TODO: because this global ccError is a global shared variable,
+ // we have to use project-dependent function to format the final message
+ _GP(ccError).ErrorString = cc_format_error(displbuf);
+ _GP(ccError).CallStack = cc_get_callstack();
_GP(ccError).HasError = 1;
_GP(ccError).Line = _G(currentline);
}
diff --git a/engines/ags/shared/script/cc_common.h b/engines/ags/shared/script/cc_common.h
index 8c0678aab04..e2a2b6cc242 100644
--- a/engines/ags/shared/script/cc_common.h
+++ b/engines/ags/shared/script/cc_common.h
@@ -55,6 +55,8 @@ void cc_clear_error();
bool cc_has_error();
const ScriptError &cc_get_error();
void cc_error(const char *, ...);
+// Project-dependent script error formatting
+AGS::Shared::String cc_format_error(const AGS::Shared::String &message);
} // namespace AGS3
Commit: faa858a55b2d64cdf3b0f88be01cd843bfc123d9
https://github.com/scummvm/scummvm/commit/faa858a55b2d64cdf3b0f88be01cd843bfc123d9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:07-07:00
Commit Message:
AGS: Fixed sending non-error messages to debugger
>From upstream 3b43353986ca91ecad9c5270e362c8716effaf37
Changed paths:
engines/ags/engine/debugging/debug.cpp
engines/ags/engine/script/script.h
engines/ags/shared/script/cc_common.cpp
diff --git a/engines/ags/engine/debugging/debug.cpp b/engines/ags/engine/debugging/debug.cpp
index 3b0644d8c32..6c9bdba5bdd 100644
--- a/engines/ags/engine/debugging/debug.cpp
+++ b/engines/ags/engine/debugging/debug.cpp
@@ -22,13 +22,6 @@
#include "ags/lib/std/memory.h"
#include "ags/lib/std/limits.h"
#include "ags/shared/core/platform.h"
-#if AGS_PLATFORM_OS_WINDOWS
-#define NOMINMAX
-#define BITMAP WINDOWS_BITMAP
-//include <windows.h>
-#undef BITMAP
-#endif
-//include <SDL.h>
#include "ags/lib/std/initializer_list.h"
#include "ags/shared/ac/common.h"
#include "ags/shared/ac/game_setup_struct.h"
@@ -321,23 +314,24 @@ struct Breakpoint {
};
bool send_message_to_editor(const char *msg, const char *errorMsg) {
- String callStack = cc_get_error().CallStack;
+ // Get either saved callstack from a script error, or current execution point
+ String callStack = (errorMsg && cc_has_error()) ?
+ cc_get_error().CallStack : cc_get_callstack();
if (callStack.IsEmpty())
return false;
- char messageToSend[STD_BUFFER_SIZE];
- sprintf(messageToSend, "<?xml version=\"1.0\" encoding=\"Windows-1252\"?><Debugger Command=\"%s\">", msg);
+ String message;
+ message.AppendFmt("<?xml version=\"1.0\" encoding=\"Windows-1252\"?><Debugger Command=\"%s\">", msg);
#if AGS_PLATFORM_OS_WINDOWS
- sprintf(&messageToSend[strlen(messageToSend)], " <EngineWindow>%d</EngineWindow> ", (int)sys_win_get_window());
+ message.AppendFmt(" <EngineWindow>%d</EngineWindow> ", (int)sys_win_get_window());
#endif
- sprintf(&messageToSend[strlen(messageToSend)], " <ScriptState><![CDATA[%s]]></ScriptState> ", callStack.GetCStr());
+ message.AppendFmt(" <ScriptState><![CDATA[%s]]></ScriptState> ", callStack.GetCStr());
if (errorMsg != nullptr) {
- sprintf(&messageToSend[strlen(messageToSend)], " <ErrorMessage><![CDATA[%s]]></ErrorMessage> ", errorMsg);
+ message.AppendFmt(" <ErrorMessage><![CDATA[%s]]></ErrorMessage> ", errorMsg);
}
- strcat(messageToSend, "</Debugger>");
-
- _G(editor_debugger)->SendMessageToEditor(messageToSend);
+ message.Append("</Debugger>");
+ _G(editor_debugger)->SendMessageToEditor(message.GetCStr());
return true;
}
diff --git a/engines/ags/engine/script/script.h b/engines/ags/engine/script/script.h
index 3b221bc2f7f..622741aa4d7 100644
--- a/engines/ags/engine/script/script.h
+++ b/engines/ags/engine/script/script.h
@@ -88,6 +88,7 @@ void can_run_delayed_command();
// Gets current running script position
bool get_script_position(ScriptPosition &script_pos);
+AGS::Shared::String cc_get_callstack(int max_lines = INT_MAX);
} // namespace AGS3
diff --git a/engines/ags/shared/script/cc_common.cpp b/engines/ags/shared/script/cc_common.cpp
index 67d165376f6..76bc36a3415 100644
--- a/engines/ags/shared/script/cc_common.cpp
+++ b/engines/ags/shared/script/cc_common.cpp
@@ -42,9 +42,6 @@ int ccGetOption(int optbit) {
return 0;
}
-// Returns current running script callstack as a human-readable text
-extern String cc_get_callstack(int max_lines = INT_MAX);
-
void cc_clear_error() {
_GP(ccError) = ScriptError();
}
Commit: 6482e3880343594e8e388e7f5cfec22a330105af
https://github.com/scummvm/scummvm/commit/6482e3880343594e8e388e7f5cfec22a330105af
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:08-07:00
Commit Message:
AGS: CharacterExtras and MoveLists are stored in std::vector
>From upstream 0c81cfefb788c0dcfdb2cad914f939f28110edca
Changed paths:
engines/ags/engine/ac/character.cpp
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/game.cpp
engines/ags/engine/ac/global_character.cpp
engines/ags/engine/ac/global_debug.cpp
engines/ags/engine/ac/global_room.cpp
engines/ags/engine/ac/gui_inv.cpp
engines/ags/engine/ac/inv_window.cpp
engines/ags/engine/ac/object.cpp
engines/ags/engine/ac/overlay.cpp
engines/ags/engine/ac/room.cpp
engines/ags/engine/ac/route_finder_impl.cpp
engines/ags/engine/ac/route_finder_impl_legacy.cpp
engines/ags/engine/game/game_init.cpp
engines/ags/engine/game/savegame_components.cpp
engines/ags/engine/game/savegame_v321.cpp
engines/ags/engine/main/engine.cpp
engines/ags/engine/main/game_run.cpp
engines/ags/engine/main/update.cpp
engines/ags/globals.cpp
engines/ags/globals.h
engines/ags/plugins/ags_plugin.cpp
diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index cf854d17eaf..7a6f6937dd1 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -96,8 +96,8 @@ void Character_AddInventory(CharacterInfo *chaa, ScriptInvItem *invi, int addInd
if (_GP(game).options[OPT_DUPLICATEINV] == 0) {
// Ensure it is only in the list once
- for (ee = 0; ee < _G(charextra)[charid].invorder_count; ee++) {
- if (_G(charextra)[charid].invorder[ee] == inum) {
+ for (ee = 0; ee < _GP(charextra)[charid].invorder_count; ee++) {
+ if (_GP(charextra)[charid].invorder[ee] == inum) {
// They already have the item, so don't add it to the list
if (chaa == _G(playerchar))
run_on_event(GE_ADD_INV, RuntimeScriptValue().SetInt32(inum));
@@ -105,22 +105,22 @@ void Character_AddInventory(CharacterInfo *chaa, ScriptInvItem *invi, int addInd
}
}
}
- if (_G(charextra)[charid].invorder_count >= MAX_INVORDER)
+ if (_GP(charextra)[charid].invorder_count >= MAX_INVORDER)
quit("!Too many inventory items added, max 500 display at one time");
if ((addIndex == SCR_NO_VALUE) ||
- (addIndex >= _G(charextra)[charid].invorder_count) ||
+ (addIndex >= _GP(charextra)[charid].invorder_count) ||
(addIndex < 0)) {
// add new item at end of list
- _G(charextra)[charid].invorder[_G(charextra)[charid].invorder_count] = inum;
+ _GP(charextra)[charid].invorder[_GP(charextra)[charid].invorder_count] = inum;
} else {
// insert new item at index
- for (ee = _G(charextra)[charid].invorder_count - 1; ee >= addIndex; ee--)
- _G(charextra)[charid].invorder[ee + 1] = _G(charextra)[charid].invorder[ee];
+ for (ee = _GP(charextra)[charid].invorder_count - 1; ee >= addIndex; ee--)
+ _GP(charextra)[charid].invorder[ee + 1] = _GP(charextra)[charid].invorder[ee];
- _G(charextra)[charid].invorder[addIndex] = inum;
+ _GP(charextra)[charid].invorder[addIndex] = inum;
}
- _G(charextra)[charid].invorder_count++;
+ _GP(charextra)[charid].invorder_count++;
GUI::MarkInventoryForUpdate(charid, charid == _GP(game).playercharacter);
if (chaa == _G(playerchar))
run_on_event(GE_ADD_INV, RuntimeScriptValue().SetInt32(inum));
@@ -137,7 +137,7 @@ void Character_AddWaypoint(CharacterInfo *chaa, int x, int y) {
return;
}
- MoveList *cmls = &_G(mls)[chaa->walking % TURNING_AROUND];
+ MoveList *cmls = &_GP(mls)[chaa->walking % TURNING_AROUND];
if (cmls->numstage >= MAXNEEDSTAGES) {
debug_script_warn("Character_AddWaypoint: move is too complex, cannot add any further paths");
return;
@@ -263,7 +263,7 @@ void Character_ChangeView(CharacterInfo *chap, int vii) {
chap->frame = 0;
chap->wait = 0;
chap->walkwait = 0;
- _G(charextra)[chap->index_id].animwait = 0;
+ _GP(charextra)[chap->index_id].animwait = 0;
FindReasonableLoopForCharacter(chap);
}
@@ -651,11 +651,11 @@ void Character_LoseInventory(CharacterInfo *chap, ScriptInvItem *invi) {
if ((chap->inv[inum] == 0) || (_GP(game).options[OPT_DUPLICATEINV] > 0)) {
int xx, tt;
- for (xx = 0; xx < _G(charextra)[charid].invorder_count; xx++) {
- if (_G(charextra)[charid].invorder[xx] == inum) {
- _G(charextra)[charid].invorder_count--;
- for (tt = xx; tt < _G(charextra)[charid].invorder_count; tt++)
- _G(charextra)[charid].invorder[tt] = _G(charextra)[charid].invorder[tt + 1];
+ for (xx = 0; xx < _GP(charextra)[charid].invorder_count; xx++) {
+ if (_GP(charextra)[charid].invorder[xx] == inum) {
+ _GP(charextra)[charid].invorder_count--;
+ for (tt = xx; tt < _GP(charextra)[charid].invorder_count; tt++)
+ _GP(charextra)[charid].invorder[tt] = _GP(charextra)[charid].invorder[tt + 1];
break;
}
}
@@ -786,7 +786,7 @@ void Character_SetIdleView(CharacterInfo *chaa, int iview, int itime) {
}
// if they switch to a swimming animation, kick it off immediately
if (itime == 0)
- _G(charextra)[chaa->index_id].process_idle_this_time = 1;
+ _GP(charextra)[chaa->index_id].process_idle_this_time = 1;
}
@@ -795,35 +795,35 @@ bool Character_GetHasExplicitLight(CharacterInfo *ch) {
}
int Character_GetLightLevel(CharacterInfo *ch) {
- return ch->has_explicit_light() ? _G(charextra)[ch->index_id].tint_light : 0;
+ return ch->has_explicit_light() ? _GP(charextra)[ch->index_id].tint_light : 0;
}
void Character_SetLightLevel(CharacterInfo *chaa, int light_level) {
light_level = Math::Clamp(light_level, -100, 100);
- _G(charextra)[chaa->index_id].tint_light = light_level;
+ _GP(charextra)[chaa->index_id].tint_light = light_level;
chaa->flags &= ~CHF_HASTINT;
chaa->flags |= CHF_HASLIGHT;
}
int Character_GetTintRed(CharacterInfo *ch) {
- return ch->has_explicit_tint() ? _G(charextra)[ch->index_id].tint_r : 0;
+ return ch->has_explicit_tint() ? _GP(charextra)[ch->index_id].tint_r : 0;
}
int Character_GetTintGreen(CharacterInfo *ch) {
- return ch->has_explicit_tint() ? _G(charextra)[ch->index_id].tint_g : 0;
+ return ch->has_explicit_tint() ? _GP(charextra)[ch->index_id].tint_g : 0;
}
int Character_GetTintBlue(CharacterInfo *ch) {
- return ch->has_explicit_tint() ? _G(charextra)[ch->index_id].tint_b : 0;
+ return ch->has_explicit_tint() ? _GP(charextra)[ch->index_id].tint_b : 0;
}
int Character_GetTintSaturation(CharacterInfo *ch) {
- return ch->has_explicit_tint() ? _G(charextra)[ch->index_id].tint_level : 0;
+ return ch->has_explicit_tint() ? _GP(charextra)[ch->index_id].tint_level : 0;
}
int Character_GetTintLuminance(CharacterInfo *ch) {
- return ch->has_explicit_tint() ? ((_G(charextra)[ch->index_id].tint_light * 10) / 25) : 0;
+ return ch->has_explicit_tint() ? ((_GP(charextra)[ch->index_id].tint_light * 10) / 25) : 0;
}
void Character_SetOption(CharacterInfo *chaa, int flag, int yesorno) {
@@ -867,21 +867,21 @@ void Character_StopMoving(CharacterInfo *charp) {
if (chaa == _GP(play).skip_until_char_stops)
EndSkippingUntilCharStops();
- if (_G(charextra)[chaa].xwas != INVALID_X) {
- charp->x = _G(charextra)[chaa].xwas;
- charp->y = _G(charextra)[chaa].ywas;
- _G(charextra)[chaa].xwas = INVALID_X;
+ if (_GP(charextra)[chaa].xwas != INVALID_X) {
+ charp->x = _GP(charextra)[chaa].xwas;
+ charp->y = _GP(charextra)[chaa].ywas;
+ _GP(charextra)[chaa].xwas = INVALID_X;
}
if ((charp->walking > 0) && (charp->walking < TURNING_AROUND)) {
// if it's not a MoveCharDirect, make sure they end up on a walkable area
- if ((_G(mls)[charp->walking].direct == 0) && (charp->room == _G(displayed_room)))
+ if ((_GP(mls)[charp->walking].direct == 0) && (charp->room == _G(displayed_room)))
Character_PlaceOnWalkableArea(charp);
debug_script_log("%s: stop moving", charp->scrname);
charp->idleleft = charp->idletime;
// restart the idle animation straight away
- _G(charextra)[chaa].process_idle_this_time = 1;
+ _GP(charextra)[chaa].process_idle_this_time = 1;
}
if (charp->walking) {
// If the character is currently moving, stop them and reset their frame
@@ -900,11 +900,11 @@ void Character_Tint(CharacterInfo *chaa, int red, int green, int blue, int opaci
debug_script_log("Set %s tint RGB(%d,%d,%d) %d%%", chaa->scrname, red, green, blue, opacity);
- _G(charextra)[chaa->index_id].tint_r = red;
- _G(charextra)[chaa->index_id].tint_g = green;
- _G(charextra)[chaa->index_id].tint_b = blue;
- _G(charextra)[chaa->index_id].tint_level = opacity;
- _G(charextra)[chaa->index_id].tint_light = (luminance * 25) / 10;
+ _GP(charextra)[chaa->index_id].tint_r = red;
+ _GP(charextra)[chaa->index_id].tint_g = green;
+ _GP(charextra)[chaa->index_id].tint_b = blue;
+ _GP(charextra)[chaa->index_id].tint_level = opacity;
+ _GP(charextra)[chaa->index_id].tint_light = (luminance * 25) / 10;
chaa->flags &= ~CHF_HASLIGHT;
chaa->flags |= CHF_HASTINT;
}
@@ -938,7 +938,7 @@ void Character_UnlockViewEx(CharacterInfo *chaa, int stopMoving) {
chaa->pic_xoffs = 0;
chaa->pic_yoffs = 0;
// restart the idle animation straight away
- _G(charextra)[chaa->index_id].process_idle_this_time = 1;
+ _GP(charextra)[chaa->index_id].process_idle_this_time = 1;
}
@@ -1237,7 +1237,7 @@ void Character_SetIgnoreScaling(CharacterInfo *chaa, int yesorno) {
if (yesorno) {
// when setting IgnoreScaling to 1, should reset zoom level
// like it used to in pre-2.71
- _G(charextra)[chaa->index_id].zoom = 100;
+ _GP(charextra)[chaa->index_id].zoom = 100;
}
Character_SetManualScaling(chaa, yesorno);
}
@@ -1300,7 +1300,7 @@ int Character_GetMoving(CharacterInfo *chaa) {
int Character_GetDestinationX(CharacterInfo *chaa) {
if (chaa->walking) {
- MoveList *cmls = &_G(mls)[chaa->walking % TURNING_AROUND];
+ MoveList *cmls = &_GP(mls)[chaa->walking % TURNING_AROUND];
return cmls->pos[cmls->numstage - 1] >> 16;
} else
return chaa->x;
@@ -1308,7 +1308,7 @@ int Character_GetDestinationX(CharacterInfo *chaa) {
int Character_GetDestinationY(CharacterInfo *chaa) {
if (chaa->walking) {
- MoveList *cmls = &_G(mls)[chaa->walking % TURNING_AROUND];
+ MoveList *cmls = &_GP(mls)[chaa->walking % TURNING_AROUND];
return cmls->pos[cmls->numstage - 1] & 0xFFFF;
} else
return chaa->y;
@@ -1372,7 +1372,7 @@ void Character_SetScaleVolume(CharacterInfo *chaa, int yesorno) {
}
int Character_GetScaling(CharacterInfo *chaa) {
- return _G(charextra)[chaa->index_id].zoom;
+ return _GP(charextra)[chaa->index_id].zoom;
}
void Character_SetScaling(CharacterInfo *chaa, int zoomlevel) {
@@ -1386,7 +1386,7 @@ void Character_SetScaling(CharacterInfo *chaa, int zoomlevel) {
debug_script_warn("Character.Scaling: scaling level must be between 1 and %d%%, asked for: %d",
(int)(INT16_MAX), zoomlevel);
- _G(charextra)[chaa->index_id].zoom = zoom_fixed;
+ _GP(charextra)[chaa->index_id].zoom = zoom_fixed;
}
int Character_GetSolid(CharacterInfo *chaa) {
@@ -1600,7 +1600,7 @@ void walk_character(int chac, int tox, int toy, int ignwal, bool autoWalkAnims)
// if they are currently walking, save the current Wait
if (chin->walking) {
waitWas = chin->walkwait;
- animWaitWas = _G(charextra)[chac].animwait;
+ animWaitWas = _GP(charextra)[chac].animwait;
}
StopMoving(chac);
@@ -1625,8 +1625,8 @@ void walk_character(int chac, int tox, int toy, int ignwal, bool autoWalkAnims)
set_color_depth(_GP(game).GetColorDepth());
if (mslot > 0) {
chin->walking = mslot;
- _G(mls)[mslot].direct = ignwal;
- convert_move_path_to_room_resolution(&_G(mls)[mslot]);
+ _GP(mls)[mslot].direct = ignwal;
+ convert_move_path_to_room_resolution(&_GP(mls)[mslot]);
// cancel any pending waits on current animations
// or if they were already moving, keep the current wait -
@@ -1634,10 +1634,10 @@ void walk_character(int chac, int tox, int toy, int ignwal, bool autoWalkAnims)
// are already moving
if (autoWalkAnims) {
chin->walkwait = waitWas;
- _G(charextra)[chac].animwait = animWaitWas;
+ _GP(charextra)[chac].animwait = animWaitWas;
- if (_G(mls)[mslot].pos[0] != _G(mls)[mslot].pos[1]) {
- fix_player_sprite(&_G(mls)[mslot], chin);
+ if (_GP(mls)[mslot].pos[0] != _GP(mls)[mslot].pos[1]) {
+ fix_player_sprite(&_GP(mls)[mslot], chin);
}
} else
chin->flags |= CHF_MOVENOTWALK;
@@ -1781,7 +1781,7 @@ int doNextCharMoveStep(CharacterInfo *chi, int &char_index, CharacterExtras *che
if (do_movelist_move(&chi->walking, &chi->x, &chi->y) == 2) {
if ((chi->flags & CHF_MOVENOTWALK) == 0)
- fix_player_sprite(&_G(mls)[chi->walking], chi);
+ fix_player_sprite(&_GP(mls)[chi->walking], chi);
}
ntf = has_hit_another_character(char_index);
@@ -1800,8 +1800,8 @@ int doNextCharMoveStep(CharacterInfo *chi, int &char_index, CharacterExtras *che
}
if ((chi->walking < 1) || (chi->walking >= TURNING_AROUND)) ;
- else if (_G(mls)[chi->walking].onpart > 0) {
- _G(mls)[chi->walking].onpart --;
+ else if (_GP(mls)[chi->walking].onpart > 0) {
+ _GP(mls)[chi->walking].onpart --;
chi->x = xwas;
chi->y = ywas;
}
@@ -1813,7 +1813,7 @@ int doNextCharMoveStep(CharacterInfo *chi, int &char_index, CharacterExtras *che
bool is_char_walking_ndirect(CharacterInfo *chi) {
return ((chi->walking > 0) && (chi->walking < TURNING_AROUND)) &&
- (_G(mls)[chi->walking].direct == 0);
+ (_GP(mls)[chi->walking].direct == 0);
}
int find_nearest_walkable_area_within(int *xx, int *yy, int range, int step) {
@@ -2058,7 +2058,7 @@ void CheckViewFrameForCharacter(CharacterInfo *chi) {
if (chi->flags & CHF_SCALEVOLUME) {
// adjust the sound volume using the character's zoom level
- int zoom_level = _G(charextra)[chi->index_id].zoom;
+ int zoom_level = _GP(charextra)[chi->index_id].zoom;
if (zoom_level == 0)
zoom_level = 100;
@@ -2118,8 +2118,8 @@ int is_pos_on_character(int xx, int yy) {
}
sppic = _GP(views)[chin->view].loops[chin->loop].frames[chin->frame].pic;
- int usewid = _G(charextra)[cc].width;
- int usehit = _G(charextra)[cc].height;
+ int usewid = _GP(charextra)[cc].width;
+ int usehit = _GP(charextra)[cc].height;
if (usewid == 0) usewid = _GP(game).SpriteInfos[sppic].Width;
if (usehit == 0) usehit = _GP(game).SpriteInfos[sppic].Height;
int xxx = chin->x - game_to_data_coord(usewid) / 2;
@@ -2411,7 +2411,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
if (tdyp < 0) {
int sppic = _GP(views)[speakingChar->view].loops[speakingChar->loop].frames[0].pic;
- int height = (_G(charextra)[aschar].height < 1) ? _GP(game).SpriteInfos[sppic].Height : _G(charextra)[aschar].height;
+ int height = (_GP(charextra)[aschar].height < 1) ? _GP(game).SpriteInfos[sppic].Height : _GP(charextra)[aschar].height;
tdyp = view->RoomToScreen(0, data_to_game_coord(_GP(game).chars[aschar].get_effective_y()) - height).first.Y
- get_fixed_pixel_size(5);
if (isThought) // if it's a thought, lift it a bit further up
@@ -2702,7 +2702,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
speakingChar->wait = 0;
speakingChar->idleleft = speakingChar->idletime;
// restart the idle animation straight away
- _G(charextra)[aschar].process_idle_this_time = 1;
+ _GP(charextra)[aschar].process_idle_this_time = 1;
}
_G(char_speaking) = -1;
_G(char_thinking) = -1;
@@ -2783,7 +2783,7 @@ int update_lip_sync(int talkview, int talkloop, int *talkframeptr) {
Rect GetCharacterRoomBBox(int charid, bool use_frame_0) {
int width, height;
- const CharacterExtras &chex = _G(charextra)[charid];
+ const CharacterExtras &chex = _GP(charextra)[charid];
const CharacterInfo &chin = _GP(game).chars[charid];
int frame = use_frame_0 ? 0 : chin.frame;
int pic = _GP(views)[chin.view].loops[chin.loop].frames[frame].pic;
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 4e7910f7cc9..f1fad499b4c 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1428,29 +1428,29 @@ void prepare_characters_for_drawing() {
// calculates the zoom level
if (chin->flags & CHF_MANUALSCALING) // character ignores scaling
- zoom_level = _G(charextra)[aa].zoom;
+ zoom_level = _GP(charextra)[aa].zoom;
else if ((onarea <= 0) && (_GP(thisroom).WalkAreas[0].ScalingFar == 0)) {
- zoom_level = _G(charextra)[aa].zoom;
+ zoom_level = _GP(charextra)[aa].zoom;
// NOTE: room objects don't have this fix
if (zoom_level == 0)
zoom_level = 100;
} else
zoom_level = get_area_scaling(onarea, chin->x, chin->y);
- _G(charextra)[aa].zoom = zoom_level;
+ _GP(charextra)[aa].zoom = zoom_level;
tint_red = tint_green = tint_blue = tint_amount = tint_light = light_level = 0;
if (chin->flags & CHF_HASTINT) {
// object specific tint, use it
- tint_red = _G(charextra)[aa].tint_r;
- tint_green = _G(charextra)[aa].tint_g;
- tint_blue = _G(charextra)[aa].tint_b;
- tint_amount = _G(charextra)[aa].tint_level;
- tint_light = _G(charextra)[aa].tint_light;
+ tint_red = _GP(charextra)[aa].tint_r;
+ tint_green = _GP(charextra)[aa].tint_g;
+ tint_blue = _GP(charextra)[aa].tint_b;
+ tint_amount = _GP(charextra)[aa].tint_level;
+ tint_light = _GP(charextra)[aa].tint_light;
light_level = 0;
} else if (chin->flags & CHF_HASLIGHT) {
- light_level = _G(charextra)[aa].tint_light;
+ light_level = _GP(charextra)[aa].tint_light;
} else {
get_local_tint(chin->x, chin->y, chin->flags & CHF_NOLIGHTING,
&tint_amount, &tint_red, &tint_green, &tint_blue,
@@ -1510,13 +1510,13 @@ void prepare_characters_for_drawing() {
// it needs to be stretched, so calculate the new dimensions
scale_sprite_size(sppic, zoom_level, &newwidth, &newheight);
- _G(charextra)[aa].width = newwidth;
- _G(charextra)[aa].height = newheight;
+ _GP(charextra)[aa].width = newwidth;
+ _GP(charextra)[aa].height = newheight;
} else {
// draw at original size, so just use the sprite width and height
// TODO: store width and height always, that's much simplier to use for reference!
- _G(charextra)[aa].width = 0;
- _G(charextra)[aa].height = 0;
+ _GP(charextra)[aa].width = 0;
+ _GP(charextra)[aa].height = 0;
newwidth = src_sprwidth;
newheight = src_sprheight;
}
@@ -2280,7 +2280,7 @@ void update_room_debug() {
int mlsnum = _GP(game).chars[_G(debugMoveListChar)].walking;
if (_GP(game).chars[_G(debugMoveListChar)].walking >= TURNING_AROUND)
mlsnum %= TURNING_AROUND;
- const MoveList &cmls = _G(mls)[mlsnum];
+ const MoveList &cmls = _GP(mls)[mlsnum];
for (int i = 0; i < cmls.numstage - 1; i++) {
short srcx = short((cmls.pos[i] >> 16) & 0x00ffff);
short srcy = short(cmls.pos[i] & 0x00ffff);
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 11b27cf73f3..3c1726cd9f6 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -45,6 +45,7 @@
#include "ags/shared/ac/keycode.h"
#include "ags/engine/ac/lip_sync.h"
#include "ags/engine/ac/mouse.h"
+#include "ags/engine/ac/move_list.h"
#include "ags/engine/ac/object_cache.h"
#include "ags/engine/ac/overlay.h"
#include "ags/engine/ac/path_helper.h"
@@ -363,10 +364,8 @@ void unload_game_file() {
_GP(play).FreeViewportsAndCameras();
_GP(characterScriptObjNames).clear();
- free(_G(charextra));
- _G(charextra) = nullptr;
- free(_G(mls));
- _G(mls) = nullptr;
+ _GP(charextra).clear();
+ _GP(mls).clear();
dispose_game_drawdata();
diff --git a/engines/ags/engine/ac/global_character.cpp b/engines/ags/engine/ac/global_character.cpp
index 0b415ab50c9..971db404b7b 100644
--- a/engines/ags/engine/ac/global_character.cpp
+++ b/engines/ags/engine/ac/global_character.cpp
@@ -113,7 +113,7 @@ void SetCharacterIdle(int who, int iview, int itime) {
int GetCharacterWidth(int ww) {
CharacterInfo *char1 = &_GP(game).chars[ww];
- if (_G(charextra)[ww].width < 1) {
+ if (_GP(charextra)[ww].width < 1) {
if ((char1->view < 0) ||
(char1->loop >= _GP(views)[char1->view].numLoops) ||
(char1->frame >= _GP(views)[char1->view].loops[char1->loop].numFrames)) {
@@ -123,13 +123,13 @@ int GetCharacterWidth(int ww) {
return _GP(game).SpriteInfos[_GP(views)[char1->view].loops[char1->loop].frames[char1->frame].pic].Width;
} else
- return _G(charextra)[ww].width;
+ return _GP(charextra)[ww].width;
}
int GetCharacterHeight(int charid) {
CharacterInfo *char1 = &_GP(game).chars[charid];
- if (_G(charextra)[charid].height < 1) {
+ if (_GP(charextra)[charid].height < 1) {
if ((char1->view < 0) ||
(char1->loop >= _GP(views)[char1->view].numLoops) ||
(char1->frame >= _GP(views)[char1->view].loops[char1->loop].numFrames)) {
@@ -139,7 +139,7 @@ int GetCharacterHeight(int charid) {
return _GP(game).SpriteInfos[_GP(views)[char1->view].loops[char1->loop].frames[char1->frame].pic].Height;
} else
- return _G(charextra)[charid].height;
+ return _GP(charextra)[charid].height;
}
@@ -465,7 +465,7 @@ void SetActiveInventory(int iit) {
void update_invorder() {
for (int cc = 0; cc < _GP(game).numcharacters; cc++) {
- _G(charextra)[cc].invorder_count = 0;
+ _GP(charextra)[cc].invorder_count = 0;
int ff, howmany;
// Iterate through all inv items, adding them once (or multiple
// times if requested) to the list.
@@ -475,16 +475,16 @@ void update_invorder() {
howmany = 1;
for (int ts = 0; ts < howmany; ts++) {
- if (_G(charextra)[cc].invorder_count >= MAX_INVORDER)
+ if (_GP(charextra)[cc].invorder_count >= MAX_INVORDER)
quit("!Too many inventory items to display: 500 max");
- _G(charextra)[cc].invorder[_G(charextra)[cc].invorder_count] = ff;
- _G(charextra)[cc].invorder_count++;
+ _GP(charextra)[cc].invorder[_GP(charextra)[cc].invorder_count] = ff;
+ _GP(charextra)[cc].invorder_count++;
}
}
}
// backwards compatibility
- _GP(play).obsolete_inv_numorder = _G(charextra)[_GP(game).playercharacter].invorder_count;
+ _GP(play).obsolete_inv_numorder = _GP(charextra)[_GP(game).playercharacter].invorder_count;
GUI::MarkInventoryForUpdate(_GP(game).playercharacter, true);
}
@@ -494,7 +494,7 @@ void add_inventory(int inum) {
Character_AddInventory(_G(playerchar), &_G(scrInv)[inum], SCR_NO_VALUE);
- _GP(play).obsolete_inv_numorder = _G(charextra)[_GP(game).playercharacter].invorder_count;
+ _GP(play).obsolete_inv_numorder = _GP(charextra)[_GP(game).playercharacter].invorder_count;
}
void lose_inventory(int inum) {
@@ -503,7 +503,7 @@ void lose_inventory(int inum) {
Character_LoseInventory(_G(playerchar), &_G(scrInv)[inum]);
- _GP(play).obsolete_inv_numorder = _G(charextra)[_GP(game).playercharacter].invorder_count;
+ _GP(play).obsolete_inv_numorder = _GP(charextra)[_GP(game).playercharacter].invorder_count;
}
void AddInventoryToCharacter(int charid, int inum) {
diff --git a/engines/ags/engine/ac/global_debug.cpp b/engines/ags/engine/ac/global_debug.cpp
index 20f75b3a816..7874a530fb6 100644
--- a/engines/ags/engine/ac/global_debug.cpp
+++ b/engines/ags/engine/ac/global_debug.cpp
@@ -140,7 +140,7 @@ void script_debug(int cmdd, int dataa) {
int mlsnum = _GP(game).chars[dataa].walking;
if (_GP(game).chars[dataa].walking >= TURNING_AROUND)
mlsnum %= TURNING_AROUND;
- MoveList *cmls = &_G(mls)[mlsnum];
+ MoveList *cmls = &_GP(mls)[mlsnum];
for (int i = 0; i < cmls->numstage - 1; i++) {
short srcx = short((cmls->pos[i] >> 16) & 0x00ffff);
short srcy = short(cmls->pos[i] & 0x00ffff);
diff --git a/engines/ags/engine/ac/global_room.cpp b/engines/ags/engine/ac/global_room.cpp
index 121962c9733..ae78481ef05 100644
--- a/engines/ags/engine/ac/global_room.cpp
+++ b/engines/ags/engine/ac/global_room.cpp
@@ -124,7 +124,7 @@ void NewRoom(int nrnum) {
if (is_char_walking_ndirect(_G(playerchar))) {
// nasty hack - make sure it doesn't move the character
// to a walkable area
- _G(mls)[_G(playerchar)->walking].direct = 1;
+ _GP(mls)[_G(playerchar)->walking].direct = 1;
StopMoving(_GP(game).playercharacter);
}
} else if (_G(in_graph_script))
diff --git a/engines/ags/engine/ac/gui_inv.cpp b/engines/ags/engine/ac/gui_inv.cpp
index 813f581adee..f424cf636d8 100644
--- a/engines/ags/engine/ac/gui_inv.cpp
+++ b/engines/ags/engine/ac/gui_inv.cpp
@@ -53,7 +53,7 @@ void GUIInvWindow::Draw(Bitmap *ds, int x, int y) {
// backwards compatibility
_GP(play).inv_numinline = ColCount;
_GP(play).inv_numdisp = RowCount * ColCount;
- _GP(play).obsolete_inv_numorder = _G(charextra)[_GP(game).playercharacter].invorder_count;
+ _GP(play).obsolete_inv_numorder = _GP(charextra)[_GP(game).playercharacter].invorder_count;
// if the user changes top_inv_item, switch into backwards
// compatibiltiy mode
if (_GP(play).inv_top)
@@ -66,12 +66,12 @@ void GUIInvWindow::Draw(Bitmap *ds, int x, int y) {
int at_x = x;
int at_y = y;
int lastItem = TopItem + (ColCount * RowCount);
- if (lastItem > _G(charextra)[GetCharacterId()].invorder_count)
- lastItem = _G(charextra)[GetCharacterId()].invorder_count;
+ if (lastItem > _GP(charextra)[GetCharacterId()].invorder_count)
+ lastItem = _GP(charextra)[GetCharacterId()].invorder_count;
for (int item = TopItem; item < lastItem; ++item) {
// draw inv graphic
- draw_gui_sprite(ds, _GP(game).invinfo[_G(charextra)[GetCharacterId()].invorder[item]].pic, at_x, at_y, true);
+ draw_gui_sprite(ds, _GP(game).invinfo[_GP(charextra)[GetCharacterId()].invorder[item]].pic, at_x, at_y, true);
at_x += data_to_game_coord(ItemWidth);
// go to next row when appropriate
diff --git a/engines/ags/engine/ac/inv_window.cpp b/engines/ags/engine/ac/inv_window.cpp
index 0a4f388465d..c383fc5751e 100644
--- a/engines/ags/engine/ac/inv_window.cpp
+++ b/engines/ags/engine/ac/inv_window.cpp
@@ -108,7 +108,7 @@ int InvWindow_GetItemsPerRow(GUIInvWindow *guii) {
}
int InvWindow_GetItemCount(GUIInvWindow *guii) {
- return _G(charextra)[guii->GetCharacterId()].invorder_count;
+ return _GP(charextra)[guii->GetCharacterId()].invorder_count;
}
int InvWindow_GetRowCount(GUIInvWindow *guii) {
@@ -116,7 +116,7 @@ int InvWindow_GetRowCount(GUIInvWindow *guii) {
}
void InvWindow_ScrollDown(GUIInvWindow *guii) {
- if ((_G(charextra)[guii->GetCharacterId()].invorder_count) >
+ if ((_GP(charextra)[guii->GetCharacterId()].invorder_count) >
(guii->TopItem + (guii->ColCount * guii->RowCount))) {
guii->TopItem += guii->ColCount;
guii->MarkChanged();
@@ -134,9 +134,9 @@ void InvWindow_ScrollUp(GUIInvWindow *guii) {
}
ScriptInvItem *InvWindow_GetItemAtIndex(GUIInvWindow *guii, int index) {
- if ((index < 0) || (index >= _G(charextra)[guii->GetCharacterId()].invorder_count))
+ if ((index < 0) || (index >= _GP(charextra)[guii->GetCharacterId()].invorder_count))
return nullptr;
- return &_G(scrInv)[_G(charextra)[guii->GetCharacterId()].invorder[index]];
+ return &_G(scrInv)[_GP(charextra)[guii->GetCharacterId()].invorder[index]];
}
//=============================================================================
@@ -153,10 +153,10 @@ int offset_over_inv(GUIInvWindow *inv) {
return -1;
mover += inv->TopItem;
- if ((mover < 0) || (mover >= _G(charextra)[inv->GetCharacterId()].invorder_count))
+ if ((mover < 0) || (mover >= _GP(charextra)[inv->GetCharacterId()].invorder_count))
return -1;
- return _G(charextra)[inv->GetCharacterId()].invorder[mover];
+ return _GP(charextra)[inv->GetCharacterId()].invorder[mover];
}
//
@@ -237,9 +237,9 @@ int InventoryScreen::Redraw() {
numitems = 0;
widest = 0;
highest = 0;
- if (_G(charextra)[_GP(game).playercharacter].invorder_count < 0)
+ if (_GP(charextra)[_GP(game).playercharacter].invorder_count < 0)
update_invorder();
- if (_G(charextra)[_GP(game).playercharacter].invorder_count == 0) {
+ if (_GP(charextra)[_GP(game).playercharacter].invorder_count == 0) {
DisplayMessage(996);
_G(in_inv_screen)--;
return -1;
@@ -251,17 +251,17 @@ int InventoryScreen::Redraw() {
return -1;
}
- for (int i = 0; i < _G(charextra)[_GP(game).playercharacter].invorder_count; ++i) {
- if (_GP(game).invinfo[_G(charextra)[_GP(game).playercharacter].invorder[i]].name[0] != 0) {
- dii[numitems].num = _G(charextra)[_GP(game).playercharacter].invorder[i];
- dii[numitems].sprnum = _GP(game).invinfo[_G(charextra)[_GP(game).playercharacter].invorder[i]].pic;
+ for (int i = 0; i < _GP(charextra)[_GP(game).playercharacter].invorder_count; ++i) {
+ if (_GP(game).invinfo[_GP(charextra)[_GP(game).playercharacter].invorder[i]].name[0] != 0) {
+ dii[numitems].num = _GP(charextra)[_GP(game).playercharacter].invorder[i];
+ dii[numitems].sprnum = _GP(game).invinfo[_GP(charextra)[_GP(game).playercharacter].invorder[i]].pic;
int snn = dii[numitems].sprnum;
if (_GP(game).SpriteInfos[snn].Width > widest) widest = _GP(game).SpriteInfos[snn].Width;
if (_GP(game).SpriteInfos[snn].Height > highest) highest = _GP(game).SpriteInfos[snn].Height;
numitems++;
}
}
- if (numitems != _G(charextra)[_GP(game).playercharacter].invorder_count)
+ if (numitems != _GP(charextra)[_GP(game).playercharacter].invorder_count)
quit("inconsistent inventory calculations");
widest += get_fixed_pixel_size(4);
diff --git a/engines/ags/engine/ac/object.cpp b/engines/ags/engine/ac/object.cpp
index 953de11aea3..dd2a907d261 100644
--- a/engines/ags/engine/ac/object.cpp
+++ b/engines/ags/engine/ac/object.cpp
@@ -439,8 +439,8 @@ void move_object(int objj, int tox, int toy, int spee, int ignwal) {
set_color_depth(_GP(game).GetColorDepth());
if (mslot > 0) {
_G(objs)[objj].moving = mslot;
- _G(mls)[mslot].direct = ignwal;
- convert_move_path_to_room_resolution(&_G(mls)[mslot]);
+ _GP(mls)[mslot].direct = ignwal;
+ convert_move_path_to_room_resolution(&_GP(mls)[mslot]);
}
}
diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index 2966b1c4daa..5ddb24a4f96 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -357,7 +357,7 @@ void get_overlay_position(const ScreenOverlay &over, int *x, int *y) {
auto view = FindNearestViewport(charid);
const int charpic = _GP(views)[_GP(game).chars[charid].view].loops[_GP(game).chars[charid].loop].frames[0].pic;
- const int height = (_G(charextra)[charid].height < 1) ? _GP(game).SpriteInfos[charpic].Height : _G(charextra)[charid].height;
+ const int height = (_GP(charextra)[charid].height < 1) ? _GP(game).SpriteInfos[charpic].Height : _GP(charextra)[charid].height;
Point screenpt = view->RoomToScreen(
data_to_game_coord(_GP(game).chars[charid].x),
data_to_game_coord(_GP(game).chars[charid].get_effective_y()) - height).first;
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 52d39b34c24..3bda6104694 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -279,7 +279,7 @@ void unload_old_room() {
_G(charcache)[ff].inUse = 0;
}
// ensure that any half-moves (eg. with scaled movement) are stopped
- _G(charextra)[ff].xwas = INVALID_X;
+ _GP(charextra)[ff].xwas = INVALID_X;
}
_GP(play).swap_portrait_lastchar = -1;
diff --git a/engines/ags/engine/ac/route_finder_impl.cpp b/engines/ags/engine/ac/route_finder_impl.cpp
index abc1a92b824..faea6490527 100644
--- a/engines/ags/engine/ac/route_finder_impl.cpp
+++ b/engines/ags/engine/ac/route_finder_impl.cpp
@@ -230,22 +230,22 @@ int find_route(short srcx, short srcy, short xx, short yy, Bitmap *onscreen, int
#endif
int mlist = movlst;
- _G(mls)[mlist].numstage = _G(num_navpoints);
- memcpy(&_G(mls)[mlist].pos[0], &_G(navpoints)[0], sizeof(int) * _G(num_navpoints));
+ _GP(mls)[mlist].numstage = _G(num_navpoints);
+ memcpy(&_GP(mls)[mlist].pos[0], &_G(navpoints)[0], sizeof(int) * _G(num_navpoints));
#ifdef DEBUG_PATHFINDER
AGS::Shared::Debug::Printf("stages: %d\n", _G(num_navpoints));
#endif
for (i = 0; i < _G(num_navpoints) - 1; i++)
- calculate_move_stage(&_G(mls)[mlist], i);
-
- _G(mls)[mlist].fromx = srcx;
- _G(mls)[mlist].fromy = srcy;
- _G(mls)[mlist].onstage = 0;
- _G(mls)[mlist].onpart = 0;
- _G(mls)[mlist].doneflag = 0;
- _G(mls)[mlist].lastx = -1;
- _G(mls)[mlist].lasty = -1;
+ calculate_move_stage(&_GP(mls)[mlist], i);
+
+ _GP(mls)[mlist].fromx = srcx;
+ _GP(mls)[mlist].fromy = srcy;
+ _GP(mls)[mlist].onstage = 0;
+ _GP(mls)[mlist].onpart = 0;
+ _GP(mls)[mlist].doneflag = 0;
+ _GP(mls)[mlist].lastx = -1;
+ _GP(mls)[mlist].lasty = -1;
return mlist;
}
diff --git a/engines/ags/engine/ac/route_finder_impl_legacy.cpp b/engines/ags/engine/ac/route_finder_impl_legacy.cpp
index 11adc664fc1..12c45378604 100644
--- a/engines/ags/engine/ac/route_finder_impl_legacy.cpp
+++ b/engines/ags/engine/ac/route_finder_impl_legacy.cpp
@@ -733,7 +733,7 @@ void calculate_move_stage(MoveList *mlsp, int aaa) {
int find_route(short srcx, short srcy, short xx, short yy, Bitmap *onscreen, int movlst, int nocross, int ignore_walls) {
assert(onscreen != nullptr);
- assert(_G(mls) != nullptr);
+ assert((int)_GP(mls).size() > movlst);
assert(pathbackx != nullptr);
assert(pathbacky != nullptr);
@@ -843,23 +843,23 @@ stage_again:
AGS::Shared::Debug::Printf("Route from %d,%d to %d,%d - %d stage, %d stages", orisrcx, orisrcy, xx, yy, pathbackstage, numstages);
#endif
int mlist = movlst;
- _G(mls)[mlist].numstage = numstages;
- memcpy(&_G(mls)[mlist].pos[0], &reallyneed[0], sizeof(int) * numstages);
+ _GP(mls)[mlist].numstage = numstages;
+ memcpy(&_GP(mls)[mlist].pos[0], &reallyneed[0], sizeof(int) * numstages);
#ifdef DEBUG_PATHFINDER
AGS::Shared::Debug::Printf("stages: %d\n", numstages);
#endif
for (aaa = 0; aaa < numstages - 1; aaa++) {
- calculate_move_stage(&_G(mls)[mlist], aaa);
+ calculate_move_stage(&_GP(mls)[mlist], aaa);
}
- _G(mls)[mlist].fromx = orisrcx;
- _G(mls)[mlist].fromy = orisrcy;
- _G(mls)[mlist].onstage = 0;
- _G(mls)[mlist].onpart = 0;
- _G(mls)[mlist].doneflag = 0;
- _G(mls)[mlist].lastx = -1;
- _G(mls)[mlist].lasty = -1;
+ _GP(mls)[mlist].fromx = orisrcx;
+ _GP(mls)[mlist].fromy = orisrcy;
+ _GP(mls)[mlist].onstage = 0;
+ _GP(mls)[mlist].onpart = 0;
+ _GP(mls)[mlist].doneflag = 0;
+ _GP(mls)[mlist].lastx = -1;
+ _GP(mls)[mlist].lasty = -1;
#ifdef DEBUG_PATHFINDER
// getch();
#endif
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index 01aa82f49ae..e15cfa294d6 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -363,9 +363,9 @@ HGameInitError InitGameState(const LoadedGameEntities &ents, GameDataVersion dat
//
// 3. Allocate and init game objects
//
- _G(charextra) = (CharacterExtras *)calloc(game.numcharacters, sizeof(CharacterExtras));
_G(charcache) = (CharacterCache *)calloc(1, sizeof(CharacterCache) * game.numcharacters + 5);
- _G(mls) = (MoveList *)calloc(game.numcharacters + MAX_ROOM_OBJECTS + 1, sizeof(MoveList));
+ _GP(charextra).resize(game.numcharacters);
+ _GP(mls).resize(game.numcharacters + MAX_ROOM_OBJECTS + 1);
init_game_drawdata();
_GP(views) = std::move(ents.Views);
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 248511f6079..366dc3d9d50 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -483,12 +483,12 @@ HSaveError WriteCharacters(Stream *out) {
out->WriteInt32(_GP(game).numcharacters);
for (int i = 0; i < _GP(game).numcharacters; ++i) {
_GP(game).chars[i].WriteToFile(out);
- _G(charextra)[i].WriteToFile(out);
+ _GP(charextra)[i].WriteToFile(out);
Properties::WriteValues(_GP(play).charProps[i], out);
if (_G(loaded_game_file_version) <= kGameVersion_272)
WriteTimesRun272(*_GP(game).intrChar[i], out);
// character movement path cache
- _G(mls)[CHMLSOFFS + i].WriteToFile(out);
+ _GP(mls)[CHMLSOFFS + i].WriteToFile(out);
}
return HSaveError::None();
}
@@ -499,12 +499,12 @@ HSaveError ReadCharacters(Stream *in, int32_t cmp_ver, const PreservedParams & /
return err;
for (int i = 0; i < _GP(game).numcharacters; ++i) {
_GP(game).chars[i].ReadFromFile(in);
- _G(charextra)[i].ReadFromFile(in);
+ _GP(charextra)[i].ReadFromFile(in);
Properties::ReadValues(_GP(play).charProps[i], in);
if (_G(loaded_game_file_version) <= kGameVersion_272)
ReadTimesRun272(*_GP(game).intrChar[i], in);
// character movement path cache
- err = _G(mls)[CHMLSOFFS + i].ReadFromFile(in, cmp_ver > 0 ? 1 : 0);
+ err = _GP(mls)[CHMLSOFFS + i].ReadFromFile(in, cmp_ver > 0 ? 1 : 0);
if (!err)
return err;
}
@@ -919,7 +919,7 @@ HSaveError WriteThisRoom(Stream *out) {
// room object movement paths cache
out->WriteInt32(_GP(thisroom).ObjectCount + 1);
for (size_t i = 0; i < _GP(thisroom).ObjectCount + 1; ++i) {
- _G(mls)[i].WriteToFile(out);
+ _GP(mls)[i].WriteToFile(out);
}
// room music volume
@@ -966,7 +966,7 @@ HSaveError ReadThisRoom(Stream *in, int32_t cmp_ver, const PreservedParams & /*p
if (!AssertCompatLimit(err, objmls_count, CHMLSOFFS, "room object move lists"))
return err;
for (int i = 0; i < objmls_count; ++i) {
- err = _G(mls)[i].ReadFromFile(in, cmp_ver > 0 ? 1 : 0); // FIXME!!
+ err = _GP(mls)[i].ReadFromFile(in, cmp_ver > 0 ? 1 : 0); // FIXME!!
if (!err)
return err;
}
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index 18a0e73622a..27a4e9bdc93 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -173,7 +173,7 @@ static void restore_game_play(Stream *in, RestoredData &r_data) {
static void ReadMoveList_Aligned(Stream *in) {
AlignedStream align_s(in, Shared::kAligned_Read);
for (int i = 0; i < _GP(game).numcharacters + MAX_ROOM_OBJECTS + 1; ++i) {
- _G(mls)[i].ReadFromFile_Legacy(&align_s);
+ _GP(mls)[i].ReadFromFile_Legacy(&align_s);
align_s.Reset();
}
@@ -187,7 +187,7 @@ static void ReadGameSetupStructBase_Aligned(Stream *in) {
static void ReadCharacterExtras_Aligned(Stream *in) {
AlignedStream align_s(in, Shared::kAligned_Read);
for (int i = 0; i < _GP(game).numcharacters; ++i) {
- _G(charextra)[i].ReadFromFile(&align_s);
+ _GP(charextra)[i].ReadFromFile(&align_s);
align_s.Reset();
}
}
diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index 8dc889f890c..2e78e61c113 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -582,8 +582,8 @@ void engine_init_game_settings() {
_GP(game).chars[ee].baseline = -1;
_GP(game).chars[ee].walkwaitcounter = 0;
_GP(game).chars[ee].z = 0;
- _G(charextra)[ee].xwas = INVALID_X;
- _G(charextra)[ee].zoom = 100;
+ _GP(charextra)[ee].xwas = INVALID_X;
+ _GP(charextra)[ee].zoom = 100;
if (_GP(game).chars[ee].view >= 0) {
// set initial loop to 0
_GP(game).chars[ee].loop = 0;
@@ -591,10 +591,10 @@ void engine_init_game_settings() {
if (_GP(views)[_GP(game).chars[ee].view].loops[0].numFrames < 1)
_GP(game).chars[ee].loop = 1;
}
- _G(charextra)[ee].process_idle_this_time = 0;
- _G(charextra)[ee].invorder_count = 0;
- _G(charextra)[ee].slow_move_counter = 0;
- _G(charextra)[ee].animwait = 0;
+ _GP(charextra)[ee].process_idle_this_time = 0;
+ _GP(charextra)[ee].invorder_count = 0;
+ _GP(charextra)[ee].slow_move_counter = 0;
+ _GP(charextra)[ee].animwait = 0;
}
_G(our_eip) = -5;
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index d0faf8a9bf5..5e826bb30d4 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -377,7 +377,7 @@ bool run_service_key_controls(KeyInput &out_key) {
_GP(game).chars[chd].x, _GP(game).chars[chd].y, _GP(game).chars[chd].z,
_GP(game).chars[chd].idleview, _GP(game).chars[chd].idletime, _GP(game).chars[chd].idleleft,
_GP(game).chars[chd].walking, _GP(game).chars[chd].animating, _GP(game).chars[chd].following,
- _GP(game).chars[chd].flags, _GP(game).chars[chd].wait, _G(charextra)[chd].zoom);
+ _GP(game).chars[chd].flags, _GP(game).chars[chd].wait, _GP(charextra)[chd].zoom);
}
Display(bigbuffer);
return false;
diff --git a/engines/ags/engine/main/update.cpp b/engines/ags/engine/main/update.cpp
index 37c4c72cbec..ac2254adf01 100644
--- a/engines/ags/engine/main/update.cpp
+++ b/engines/ags/engine/main/update.cpp
@@ -57,7 +57,7 @@ int do_movelist_move(short *mlnum, int *xx, int *yy) {
int need_to_fix_sprite = 0;
if (mlnum[0] < 1) quit("movelist_move: attempted to move on a non-exist movelist");
MoveList *cmls;
- cmls = &_G(mls)[mlnum[0]];
+ cmls = &_GP(mls)[mlnum[0]];
fixed xpermove = cmls->xpermove[cmls->onstage], ypermove = cmls->ypermove[cmls->onstage];
short targetx = short((cmls->pos[cmls->onstage + 1] >> 16) & 0x00ffff);
@@ -203,7 +203,7 @@ void update_character_move_and_anim(std::vector<int> &followingAsSheep) {
if (_GP(game).chars[aa].on != 1) continue;
CharacterInfo *chi = &_GP(game).chars[aa];
- CharacterExtras *chex = &_G(charextra)[aa];
+ CharacterExtras *chex = &_GP(charextra)[aa];
chi->UpdateMoveAndAnim(aa, chex, followingAsSheep);
}
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 8c835dc464f..9b2482eb80f 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -38,6 +38,7 @@
#include "ags/shared/gui/gui_textbox.h"
#include "ags/shared/script/cc_common.h"
#include "ags/shared/util/directory.h"
+#include "ags/engine/ac/character_extras.h"
#include "ags/engine/ac/draw.h"
#include "ags/engine/ac/draw_software.h"
#include "ags/engine/ac/event.h"
@@ -237,6 +238,8 @@ Globals::Globals() {
_scrRegion = new ScriptRegion[MAX_ROOM_REGIONS];
_scrInv = new ScriptInvItem[MAX_INV];
_objcache = new ObjectCache[MAX_ROOM_OBJECTS];
+ _charextra = new std::vector<CharacterExtras>();
+ _mls = new std::vector<MoveList>();
_views = new std::vector<ViewStruct>();
_saveGameDirectory = AGS::Shared::SAVE_FOLDER_PREFIX;
@@ -493,6 +496,8 @@ Globals::~Globals() {
delete[] _scrRegion;
delete[] _scrInv;
delete[] _objcache;
+ delete _charextra;
+ delete _mls;
delete _views;
// game_init.cpp globals
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index a3f5a7082f5..24664b0f4ea 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -430,7 +430,6 @@ public:
* @{
*/
- CharacterExtras *_charextra = nullptr;
CharacterInfo *_playerchar = nullptr;
int32_t _sc_PlayerCharPtr = 0;
int _char_lowest_yp = 0;
@@ -753,7 +752,9 @@ public:
std::vector<ViewStruct> *_views;
CharacterCache *_charcache = nullptr;
ObjectCache *_objcache;
- MoveList *_mls = nullptr;
+ std::vector<CharacterExtras> *_charextra;
+ std::vector<MoveList> *_mls;
+
GameSetup *_usetup;
AGS::Shared::String _saveGameDirectory;
AGS::Shared::String _saveGameSuffix;
diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index 4bc4e1c1526..9f978835def 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -713,21 +713,21 @@ void IAGSEngine::SimulateMouseClick(int32 button) {
}
int IAGSEngine::GetMovementPathWaypointCount(int32 pathId) {
- return _G(mls)[pathId % TURNING_AROUND].numstage;
+ return _GP(mls)[pathId % TURNING_AROUND].numstage;
}
int IAGSEngine::GetMovementPathLastWaypoint(int32 pathId) {
- return _G(mls)[pathId % TURNING_AROUND].onstage;
+ return _GP(mls)[pathId % TURNING_AROUND].onstage;
}
void IAGSEngine::GetMovementPathWaypointLocation(int32 pathId, int32 waypoint, int32 *x, int32 *y) {
- *x = (_G(mls)[pathId % TURNING_AROUND].pos[waypoint] >> 16) & 0x0000ffff;
- *y = (_G(mls)[pathId % TURNING_AROUND].pos[waypoint] & 0x0000ffff);
+ *x = (_GP(mls)[pathId % TURNING_AROUND].pos[waypoint] >> 16) & 0x0000ffff;
+ *y = (_GP(mls)[pathId % TURNING_AROUND].pos[waypoint] & 0x0000ffff);
}
void IAGSEngine::GetMovementPathWaypointSpeed(int32 pathId, int32 waypoint, int32 *xSpeed, int32 *ySpeed) {
- *xSpeed = _G(mls)[pathId % TURNING_AROUND].xpermove[waypoint];
- *ySpeed = _G(mls)[pathId % TURNING_AROUND].ypermove[waypoint];
+ *xSpeed = _GP(mls)[pathId % TURNING_AROUND].xpermove[waypoint];
+ *ySpeed = _GP(mls)[pathId % TURNING_AROUND].ypermove[waypoint];
}
int IAGSEngine::IsRunningUnderDebugger() {
Commit: a40ea44aa2e99679d7da225fcefdcc1d6f2b0b3d
https://github.com/scummvm/scummvm/commit/a40ea44aa2e99679d7da225fcefdcc1d6f2b0b3d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:08-07:00
Commit Message:
AGS: CharacterCache is stored in std::vector, hide in draw.cpp
>From upstream 417879fce0dc27d458a73fedc20f311f3305f26f
Changed paths:
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/draw.h
engines/ags/engine/ac/game.cpp
engines/ags/engine/ac/global_object.cpp
engines/ags/engine/ac/object.cpp
engines/ags/engine/ac/room.cpp
engines/ags/engine/game/game_init.cpp
engines/ags/globals.cpp
engines/ags/globals.h
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index f1fad499b4c..4ac8d0dfa82 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -386,6 +386,9 @@ void dispose_draw_method() {
}
void init_game_drawdata() {
+ // character and object caches
+ _GP(charcache).resize(_GP(game).numcharacters);
+
for (int i = 0; i < MAX_ROOM_OBJECTS; ++i)
_G(objcache)[i].image = nullptr;
@@ -407,6 +410,7 @@ void init_game_drawdata() {
void dispose_game_drawdata() {
clear_drawobj_cache();
+ _GP(charcache).clear();
_GP(actsps).clear();
_GP(walkbehindobj).clear();
@@ -426,6 +430,14 @@ void dispose_room_drawdata() {
}
void clear_drawobj_cache() {
+ // clear the character cache
+ for (auto &cc : _GP(charcache)) {
+ if (cc.inUse)
+ delete cc.image;
+ cc.image = nullptr;
+ cc.inUse = 0;
+ }
+
// clear the object cache
for (int i = 0; i < MAX_ROOM_OBJECTS; ++i) {
delete _G(objcache)[i].image;
@@ -586,6 +598,10 @@ void on_roomcamera_changed(Camera *cam) {
invalidate_screen();
}
+void mark_object_changed(int objid) {
+ _G(objcache)[objid].ywas = -9999;
+}
+
void mark_screen_dirty() {
_G(screen_is_dirty) = true;
}
@@ -1477,28 +1493,27 @@ void prepare_characters_for_drawing() {
// if the character was the same sprite and scaling last time,
// just use the cached image
- if ((_G(charcache)[aa].inUse) &&
- (_G(charcache)[aa].sppic == specialpic) &&
- (_G(charcache)[aa].scaling == zoom_level) &&
- (_G(charcache)[aa].tintredwas == tint_red) &&
- (_G(charcache)[aa].tintgrnwas == tint_green) &&
- (_G(charcache)[aa].tintbluwas == tint_blue) &&
- (_G(charcache)[aa].tintamntwas == tint_amount) &&
- (_G(charcache)[aa].tintlightwas == tint_light) &&
- (_G(charcache)[aa].lightlevwas == light_level)) {
+ if ((_GP(charcache)[aa].inUse) &&
+ (_GP(charcache)[aa].sppic == specialpic) &&
+ (_GP(charcache)[aa].scaling == zoom_level) &&
+ (_GP(charcache)[aa].tintredwas == tint_red) &&
+ (_GP(charcache)[aa].tintgrnwas == tint_green) &&
+ (_GP(charcache)[aa].tintbluwas == tint_blue) &&
+ (_GP(charcache)[aa].tintamntwas == tint_amount) &&
+ (_GP(charcache)[aa].tintlightwas == tint_light) &&
+ (_GP(charcache)[aa].lightlevwas == light_level)) {
if (_G(walkBehindMethod) == DrawOverCharSprite) {
- recycle_bitmap(actsp.Bmp, _G(charcache)[aa].image->GetColorDepth(), _G(charcache)[aa].image->GetWidth(), _G(charcache)[aa].image->GetHeight());
- actsp.Bmp->Blit(_G(charcache)[aa].image, 0, 0);
+ 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);
} else {
usingCachedImage = true;
}
- } else if ((_G(charcache)[aa].inUse) &&
- (_G(charcache)[aa].sppic == specialpic) &&
+ } else if ((_GP(charcache)[aa].inUse) &&
+ (_GP(charcache)[aa].sppic == specialpic) &&
(_G(gfxDriver)->HasAcceleratedTransform())) {
usingCachedImage = true;
- } else if (_G(charcache)[aa].inUse) {
- //destroy_bitmap (_G(charcache)[aa].image);
- _G(charcache)[aa].inUse = 0;
+ } else if (_GP(charcache)[aa].inUse) {
+ _GP(charcache)[aa].inUse = 0;
}
_G(our_eip) = 3332;
@@ -1529,17 +1544,17 @@ void prepare_characters_for_drawing() {
// adjust the Y positioning for the character's Z co-ord
- data_to_game_coord(chin->z);
- _G(charcache)[aa].scaling = zoom_level;
- _G(charcache)[aa].sppic = specialpic;
- _G(charcache)[aa].tintredwas = tint_red;
- _G(charcache)[aa].tintgrnwas = tint_green;
- _G(charcache)[aa].tintbluwas = tint_blue;
- _G(charcache)[aa].tintamntwas = tint_amount;
- _G(charcache)[aa].tintlightwas = tint_light;
- _G(charcache)[aa].lightlevwas = light_level;
+ _GP(charcache)[aa].scaling = zoom_level;
+ _GP(charcache)[aa].sppic = specialpic;
+ _GP(charcache)[aa].tintredwas = tint_red;
+ _GP(charcache)[aa].tintgrnwas = tint_green;
+ _GP(charcache)[aa].tintbluwas = tint_blue;
+ _GP(charcache)[aa].tintamntwas = tint_amount;
+ _GP(charcache)[aa].tintlightwas = tint_light;
+ _GP(charcache)[aa].lightlevwas = light_level;
// If cache needs to be re-drawn
- if (!_G(charcache)[aa].inUse) {
+ if (!_GP(charcache)[aa].inUse) {
// create the base sprite in _GP(actsps)[useindx], which will
// be scaled and/or flipped, as appropriate
@@ -1571,9 +1586,9 @@ void prepare_characters_for_drawing() {
}
// update the character cache with the new image
- _G(charcache)[aa].inUse = 1;
- _G(charcache)[aa].image = recycle_bitmap(_G(charcache)[aa].image, coldept, actsp.Bmp->GetWidth(), actsp.Bmp->GetHeight());
- _G(charcache)[aa].image->Blit(actsp.Bmp.get(), 0, 0);
+ _GP(charcache)[aa].inUse = 1;
+ _GP(charcache)[aa].image = 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 5c58d92e5cd..4c61d0da9ea 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -114,6 +114,8 @@ void on_roomviewport_changed(Viewport *view);
void detect_roomviewport_overlaps(size_t z_index);
// Updates drawing settings if room camera's size has changed
void on_roomcamera_changed(Camera *cam);
+// Marks particular object as need too update the texture
+void mark_object_changed(int objid);
// whether there are currently remnants of a DisplaySpeech
void mark_screen_dirty();
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 3c1726cd9f6..ac08772fc9f 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -407,9 +407,6 @@ void unload_game_file() {
_GP(views).clear();
- free(_G(charcache));
- _G(charcache) = nullptr;
-
if (_G(splipsync) != nullptr) {
for (int i = 0; i < _G(numLipLines); ++i) {
free(_G(splipsync)[i].endtimeoffs);
@@ -1355,8 +1352,8 @@ void game_sprite_updated(int sprnum) {
}
// character cache
for (size_t i = 0; i < (size_t)_GP(game).numcharacters; ++i) {
- if (_G(charcache)[i].sppic == sprnum)
- _G(charcache)[i].sppic = -1;
+ if (_GP(charcache)[i].sppic == sprnum)
+ _GP(charcache)[i].sppic = -1;
}
// gui backgrounds
for (size_t i = 0; i < (size_t)_GP(game).numgui; ++i) {
@@ -1391,8 +1388,8 @@ void game_sprite_deleted(int sprnum) {
}
// character cache
for (size_t i = 0; i < (size_t)_GP(game).numcharacters; ++i) {
- if (_G(charcache)[i].sppic == sprnum)
- _G(charcache)[i].sppic = -1;
+ if (_GP(charcache)[i].sppic == sprnum)
+ _GP(charcache)[i].sppic = -1;
}
// gui backgrounds
for (size_t i = 0; i < (size_t)_GP(game).numgui; ++i) {
diff --git a/engines/ags/engine/ac/global_object.cpp b/engines/ags/engine/ac/global_object.cpp
index 37091da362f..a7067fc827d 100644
--- a/engines/ags/engine/ac/global_object.cpp
+++ b/engines/ags/engine/ac/global_object.cpp
@@ -200,8 +200,8 @@ void SetObjectBaseline(int obn, int basel) {
if (!is_valid_object(obn)) quit("!SetObjectBaseline: invalid object number specified");
// baseline has changed, invalidate the cache
if (_G(objs)[obn].baseline != basel) {
- _G(objcache)[obn].ywas = -9999;
_G(objs)[obn].baseline = basel;
+ mark_object_changed(obn);
}
}
@@ -411,8 +411,7 @@ void SetObjectIgnoreWalkbehinds(int cha, int clik) {
_G(objs)[cha].flags &= ~OBJF_NOWALKBEHINDS;
if (clik)
_G(objs)[cha].flags |= OBJF_NOWALKBEHINDS;
- // clear the cache
- _G(objcache)[cha].ywas = -9999;
+ mark_object_changed(cha);
}
void RunObjectInteraction(int aa, int mood) {
diff --git a/engines/ags/engine/ac/object.cpp b/engines/ags/engine/ac/object.cpp
index dd2a907d261..e22ba59d883 100644
--- a/engines/ags/engine/ac/object.cpp
+++ b/engines/ags/engine/ac/object.cpp
@@ -333,7 +333,7 @@ void Object_SetManualScaling(ScriptObject *objj, bool on) {
if (on) _G(objs)[objj->id].flags &= ~OBJF_USEROOMSCALING;
else _G(objs)[objj->id].flags |= OBJF_USEROOMSCALING;
// clear the cache
- _G(objcache)[objj->id].ywas = -9999;
+ mark_object_changed(objj->id);
}
void Object_SetIgnoreScaling(ScriptObject *objj, int newval) {
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 3bda6104694..8554a637956 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -271,14 +271,8 @@ void unload_old_room() {
for (size_t i = 0; i < _GP(thisroom).LocalVariables.size() && i < MAX_GLOBAL_VARIABLES; ++i)
_G(croom)->interactionVariableValues[i] = _GP(thisroom).LocalVariables[i].Value;
- // wipe the character cache when we change rooms
+ // ensure that any half-moves (eg. with scaled movement) are stopped
for (ff = 0; ff < _GP(game).numcharacters; ff++) {
- if (_G(charcache)[ff].inUse) {
- delete _G(charcache)[ff].image;
- _G(charcache)[ff].image = nullptr;
- _G(charcache)[ff].inUse = 0;
- }
- // ensure that any half-moves (eg. with scaled movement) are stopped
_GP(charextra)[ff].xwas = INVALID_X;
}
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index e15cfa294d6..83add8905eb 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -363,7 +363,6 @@ HGameInitError InitGameState(const LoadedGameEntities &ents, GameDataVersion dat
//
// 3. Allocate and init game objects
//
- _G(charcache) = (CharacterCache *)calloc(1, sizeof(CharacterCache) * game.numcharacters + 5);
_GP(charextra).resize(game.numcharacters);
_GP(mls).resize(game.numcharacters + MAX_ROOM_OBJECTS + 1);
init_game_drawdata();
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 9b2482eb80f..0abe5bf48ec 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -38,6 +38,7 @@
#include "ags/shared/gui/gui_textbox.h"
#include "ags/shared/script/cc_common.h"
#include "ags/shared/util/directory.h"
+#include "ags/engine/ac/character_cache.h"
#include "ags/engine/ac/character_extras.h"
#include "ags/engine/ac/draw.h"
#include "ags/engine/ac/draw_software.h"
@@ -237,6 +238,7 @@ Globals::Globals() {
_scrHotspot = new ScriptHotspot[MAX_ROOM_HOTSPOTS];
_scrRegion = new ScriptRegion[MAX_ROOM_REGIONS];
_scrInv = new ScriptInvItem[MAX_INV];
+ _charcache = new std::vector<CharacterCache>();
_objcache = new ObjectCache[MAX_ROOM_OBJECTS];
_charextra = new std::vector<CharacterExtras>();
_mls = new std::vector<MoveList>();
@@ -495,6 +497,7 @@ Globals::~Globals() {
delete[] _scrHotspot;
delete[] _scrRegion;
delete[] _scrInv;
+ delete _charcache;
delete[] _objcache;
delete _charextra;
delete _mls;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 24664b0f4ea..1919d4c2fee 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -750,7 +750,9 @@ public:
ScriptInvItem *_scrInv;
ScriptDialog *_scrDialog = nullptr;
std::vector<ViewStruct> *_views;
- CharacterCache *_charcache = nullptr;
+ // Cached character and object states, used to determine
+ // whether these require texture update
+ std::vector<CharacterCache> *_charcache;
ObjectCache *_objcache;
std::vector<CharacterExtras> *_charextra;
std::vector<MoveList> *_mls;
Commit: 97eb5271d3e4f69d31f226ad38f53f63d944ad40
https://github.com/scummvm/scummvm/commit/97eb5271d3e4f69d31f226ad38f53f63d944ad40
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:08-07:00
Commit Message:
AGS: Added member initialization for CharacterExtras, MoveList
>From upstream 3dd153f7c4cff10ec0abfa42ca608306cc730316
Changed paths:
engines/ags/engine/ac/character_cache.h
engines/ags/engine/ac/character_extras.h
engines/ags/engine/ac/move_list.h
diff --git a/engines/ags/engine/ac/character_cache.h b/engines/ags/engine/ac/character_cache.h
index 7b0130d0e43..925075542b1 100644
--- a/engines/ags/engine/ac/character_cache.h
+++ b/engines/ags/engine/ac/character_cache.h
@@ -34,12 +34,12 @@ using namespace AGS; // FIXME later
// stores cached info about the character
struct CharacterCache {
- Shared::Bitmap *image;
- int sppic;
- int scaling;
- int inUse;
- short tintredwas, tintgrnwas, tintbluwas, tintamntwas;
- short lightlevwas, tintlightwas;
+ Shared::Bitmap *image = nullptr;
+ int sppic = 0;
+ int scaling = 0;
+ int inUse = 0;
+ short tintredwas = 0, tintgrnwas = 0, tintbluwas = 0, tintamntwas = 0;
+ short lightlevwas = 0, tintlightwas = 0;
// no mirroredWas is required, since the code inverts the sprite number
};
diff --git a/engines/ags/engine/ac/character_extras.h b/engines/ags/engine/ac/character_extras.h
index d5c48a886e4..71f71d64a54 100644
--- a/engines/ags/engine/ac/character_extras.h
+++ b/engines/ags/engine/ac/character_extras.h
@@ -37,23 +37,23 @@ using namespace AGS; // FIXME later
// The CharacterInfo struct size is fixed because it's exposed to script
// and plugin API, therefore new stuff has to go here
struct CharacterExtras {
- short invorder[MAX_INVORDER];
- short invorder_count;
- // TODO: implement full AABB and keep updated, so that engine could rely on these cached values all time;
+ short invorder[MAX_INVORDER] = {};
+ short invorder_count = 0;
+ // TODO: implement full AABB and keep updated, so that engine could rely on these cached values all time = 0;
// TODO: consider having both fixed AABB and volatile one that changes with animation frame (unless you change how anims work)
- short width;
- short height;
- short zoom;
- short xwas;
- short ywas;
- short tint_r;
- short tint_g;
- short tint_b;
- short tint_level;
- short tint_light;
- int8 process_idle_this_time;
- int8 slow_move_counter;
- short animwait;
+ short width = 0;
+ short height = 0;
+ short zoom = 0;
+ short xwas = 0;
+ short ywas = 0;
+ short tint_r = 0;
+ short tint_g = 0;
+ short tint_b = 0;
+ short tint_level = 0;
+ short tint_light = 0;
+ int8 process_idle_this_time = 0;
+ int8 slow_move_counter = 0;
+ short animwait = 0;
void ReadFromFile(Shared::Stream *in);
void WriteToFile(Shared::Stream *out);
diff --git a/engines/ags/engine/ac/move_list.h b/engines/ags/engine/ac/move_list.h
index 19fd04978c7..cc957949318 100644
--- a/engines/ags/engine/ac/move_list.h
+++ b/engines/ags/engine/ac/move_list.h
@@ -39,14 +39,14 @@ using namespace AGS; // FIXME later
#define MAXNEEDSTAGES_LEGACY 40
struct MoveList {
- int32_t pos[MAXNEEDSTAGES];
- int numstage;
- fixed xpermove[MAXNEEDSTAGES], ypermove[MAXNEEDSTAGES];
- int fromx, fromy;
- int onstage, onpart;
- int lastx, lasty;
- int8 doneflag;
- int8 direct; // MoveCharDirect was used or not
+ int32_t pos[MAXNEEDSTAGES] = {};
+ int numstage = 0;
+ fixed xpermove[MAXNEEDSTAGES] = {}, ypermove[MAXNEEDSTAGES] = {};
+ int fromx = 0, fromy = 0;
+ int onstage = 0, onpart = 0;
+ int lastx = 0, lasty = 0;
+ int8 doneflag = 0;
+ int8 direct = 0; // MoveCharDirect was used or not
void ReadFromFile_Legacy(Shared::Stream *in);
AGS::Engine::HSaveError ReadFromFile(Shared::Stream *in, int32_t cmp_ver);
Commit: a8ead540c5c6dd4a7158b2483e8c0a39ce0f18d1
https://github.com/scummvm/scummvm/commit/a8ead540c5c6dd4a7158b2483e8c0a39ce0f18d1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:08-07:00
Commit Message:
AGS: GUIControl::CalcGraphicRect returns relative rect
>From upstream f827c75396f433542b451ec4caaea4c41c22e5b2
Changed paths:
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/draw.h
engines/ags/shared/gui/gui_button.cpp
engines/ags/shared/gui/gui_label.cpp
engines/ags/shared/gui/gui_listbox.cpp
engines/ags/shared/gui/gui_main.cpp
engines/ags/shared/gui/gui_object.h
engines/ags/shared/gui/gui_slider.cpp
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 4ac8d0dfa82..696d988aa82 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -103,6 +103,7 @@ ObjTexture &ObjTexture::operator=(ObjTexture &&o) {
Ddb = o.Ddb;
o.Ddb = nullptr;
Pos = o.Pos;
+ Off = o.Off;
return *this;
}
@@ -1821,10 +1822,10 @@ void draw_gui_controls(GUIMain &gui) {
auto &objbg = _GP(guiobjbg)[draw_index];
Rect obj_surf = obj->CalcGraphicRect(GUI::Options.ClipControls);
recycle_bitmap(objbg.Bmp, _GP(game).GetColorDepth(), obj_surf.GetWidth(), obj_surf.GetHeight(), true);
- obj->Draw(objbg.Bmp.get(), obj->X - obj_surf.Left, obj->Y - obj_surf.Top);
+ obj->Draw(objbg.Bmp.get(), -obj_surf.Left, -obj_surf.Top);
sync_object_texture(objbg, obj->HasAlphaChannel());
- objbg.Pos = Point(obj_surf.GetLT());
+ objbg.Off = Point(obj_surf.GetLT());
obj->ClearChanged();
}
}
@@ -1976,14 +1977,12 @@ void draw_gui_and_overlays() {
(obj->Width <= 0 || obj->Height <= 0) ||
(!obj->IsEnabled() && (GUI::Options.DisabledStyle == kGuiDis_Blackout)))
continue;
- auto *obj_ddb = _GP(guiobjbg)[draw_index + obj_id].Ddb;
+ const auto &obj_tx = _GP(guiobjbg)[draw_index + obj_id];
+ auto *obj_ddb = obj_tx.Ddb;
assert(obj_ddb); // Test for missing texture, might happen if not marked for update
if (!obj_ddb) continue;
obj_ddb->SetAlpha(GfxDef::LegacyTrans255ToAlpha255(obj->GetTransparency()));
- _G(gfxDriver)->DrawSprite(
- _GP(guiobjbg)[draw_index + obj_id].Pos.X,
- _GP(guiobjbg)[draw_index + obj_id].Pos.Y,
- obj_ddb);
+ _G(gfxDriver)->DrawSprite(obj->X + obj_tx.Off.X, obj->Y + obj_tx.Off.Y, obj_ddb);
}
_G(gfxDriver)->EndSpriteBatch();
}
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index 4c61d0da9ea..599ea9e4b38 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -67,13 +67,15 @@ struct ObjTexture {
std::unique_ptr<Shared::Bitmap> Bmp;
// Corresponding texture, created by renderer
Engine::IDriverDependantBitmap *Ddb = nullptr;
- // Sprite's position, may be used in case the texture's pos is different
- // from the object's logical position (x,y,w,h) for some reason.
+ // Sprite's position
Point Pos;
+ // Texture's offset, *relative* to the logical sprite's position;
+ // may be used in case the texture's size is different for any reason
+ Point Off;
ObjTexture() = default;
- ObjTexture(Shared::Bitmap *bmp, Engine::IDriverDependantBitmap *ddb, int x, int y)
- : Bmp(bmp), Ddb(ddb), Pos(x, y) {
+ 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(const ObjTexture &) = default;
ObjTexture(ObjTexture &&o);
diff --git a/engines/ags/shared/gui/gui_button.cpp b/engines/ags/shared/gui/gui_button.cpp
index 63d986c59c0..7f7c2cea7fb 100644
--- a/engines/ags/shared/gui/gui_button.cpp
+++ b/engines/ags/shared/gui/gui_button.cpp
@@ -101,18 +101,19 @@ bool GUIButton::IsClippingImage() const {
Rect GUIButton::CalcGraphicRect(bool clipped) {
if (clipped)
- return RectWH(X, Y, Width, Height);
+ return RectWH(0, 0, Width, Height);
// TODO: need to find a way to cache image and text position, or there'll be some repetition
- Rect rc = RectWH(X, Y, Width, Height);
+ Rect rc = RectWH(0, 0, Width, Height);
if (IsImageButton()) {
if (IsClippingImage())
return rc;
// Main button graphic
if (_GP(spriteset)[CurrentImage] != nullptr)
- rc = SumRects(rc, RectWH(X, Y, get_adjusted_spritewidth(CurrentImage), get_adjusted_spriteheight(CurrentImage)));
+ 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) {
- Size inv_sz = Size(get_adjusted_spritewidth(_G(gui_inv_pic)), get_adjusted_spriteheight(_G(gui_inv_pic)));
+ Size inv_sz = Size(get_adjusted_spritewidth(_G(gui_inv_pic)),
+ get_adjusted_spriteheight(_G(gui_inv_pic)));
GUIButtonPlaceholder place = _placeholder;
if (place == kButtonPlace_InvItemAuto) {
place = ((inv_sz.Width > Width - 6) || (inv_sz.Height > Height - 6)) ?
@@ -120,9 +121,9 @@ Rect GUIButton::CalcGraphicRect(bool clipped) {
}
Rect inv_rc = (place == kButtonPlace_InvItemStretch) ?
- RectWH(X + 3, Y + 3, Width - 6, Height - 6) :
- RectWH(X + Width / 2 - inv_sz.Width / 2,
- Y + Height / 2 - inv_sz.Height / 2,
+ RectWH(0 + 3, 0 + 3, Width - 6, Height - 6) :
+ RectWH(0 + Width / 2 - inv_sz.Width / 2,
+ 0 + Height / 2 - inv_sz.Height / 2,
inv_sz.Width, inv_sz.Height);
rc = SumRects(rc, inv_rc);
}
@@ -130,7 +131,7 @@ Rect GUIButton::CalcGraphicRect(bool clipped) {
// Optionally merge with the button text
if (!IsImageButton() || ((_placeholder == kButtonPlace_None) && !_unnamed)) {
PrepareTextToDraw();
- Rect frame = RectWH(X + 2, Y + 2, Width - 4, Height - 4);
+ Rect frame = RectWH(0 + 2, 0 + 2, Width - 4, Height - 4);
if (IsPushed && IsMouseOver) {
frame.Left++;
frame.Top++;
diff --git a/engines/ags/shared/gui/gui_label.cpp b/engines/ags/shared/gui/gui_label.cpp
index 14957b4d73e..da049f7b58d 100644
--- a/engines/ags/shared/gui/gui_label.cpp
+++ b/engines/ags/shared/gui/gui_label.cpp
@@ -55,12 +55,12 @@ GUILabelMacro GUILabel::GetTextMacros() const {
Rect GUILabel::CalcGraphicRect(bool clipped) {
if (clipped)
- return RectWH(X, Y, Width, Height);
+ return RectWH(0, 0, Width, Height);
// TODO: need to find a way to text position, or there'll be some repetition
// have to precache text and size on some events:
// - translation change
// - macro value change (score, overhotspot etc)
- Rect rc = RectWH(X, Y, Width, Height);
+ Rect rc = RectWH(0, 0, Width, Height);
PrepareTextToDraw();
if (SplitLinesForDrawing(_GP(Lines)) == 0)
return rc;
@@ -79,7 +79,7 @@ Rect GUILabel::CalcGraphicRect(bool clipped) {
(FrameAlignment)TextAlignment);
max_line.X2 = std::max(max_line.X2, lpos.X2);
}
- return SumRects(rc, RectWH(X, Y, max_line.X2 - max_line.X1 + 1, at_y - linespacing + get_font_surface_height(Font)));
+ return SumRects(rc, RectWH(0, 0, max_line.X2 - max_line.X1 + 1, at_y - linespacing + get_font_surface_height(Font)));
}
void GUILabel::Draw(Bitmap *ds, int x, int y) {
diff --git a/engines/ags/shared/gui/gui_listbox.cpp b/engines/ags/shared/gui/gui_listbox.cpp
index 3a66f5d6f0c..3785b717a84 100644
--- a/engines/ags/shared/gui/gui_listbox.cpp
+++ b/engines/ags/shared/gui/gui_listbox.cpp
@@ -83,14 +83,15 @@ bool GUIListBox::IsInRightMargin(int x) const {
Rect GUIListBox::CalcGraphicRect(bool clipped) {
if (clipped)
- return RectWH(X, Y, Width, Height);
+ return RectWH(0, 0, Width, Height);
// TODO: need to find a way to text position, or there'll be some repetition
// have to precache text and size on some events:
// - translation change
// - macro value change (score, overhotspot etc)
- Rect rc = RectWH(X, Y, Width, Height);
+ Rect rc = RectWH(0, 0, Width, Height);
UpdateMetrics();
const int width = Width - 1;
+ const int height = Height - 1;
const int pixel_size = get_fixed_pixel_size(1);
int right_hand_edge = width - pixel_size - 1;
// calculate the scroll bar's width if necessary
@@ -105,7 +106,7 @@ Rect GUIListBox::CalcGraphicRect(bool clipped) {
(FrameAlignment)TextAlignment);
max_line.X2 = std::max(max_line.X2, lpos.X2);
}
- return SumRects(rc, RectWH(X, Y, max_line.X2 - max_line.X1 + 1, Height));
+ return SumRects(rc, RectWH(0, 0, max_line.X2 - max_line.X1 + 1, Height));
}
int GUIListBox::AddItem(const String &text) {
diff --git a/engines/ags/shared/gui/gui_main.cpp b/engines/ags/shared/gui/gui_main.cpp
index f1507ac601a..6a5f9656421 100644
--- a/engines/ags/shared/gui/gui_main.cpp
+++ b/engines/ags/shared/gui/gui_main.cpp
@@ -282,8 +282,9 @@ void GUIMain::DrawWithControls(Bitmap *ds) {
} else {
const Rect rc = objToDraw->CalcGraphicRect(GUI::Options.ClipControls && objToDraw->IsContentClipped());
tempbmp.CreateTransparent(rc.GetWidth(), rc.GetHeight());
- objToDraw->Draw(&tempbmp, objToDraw->X - rc.Left, objToDraw->Y - rc.Top);
- draw_gui_sprite(ds, true, objToDraw->X, objToDraw->Y, &tempbmp, objToDraw->HasAlphaChannel(), kBlendMode_Alpha,
+ objToDraw->Draw(&tempbmp, -rc.Left, -rc.Top);
+ draw_gui_sprite(ds, true, objToDraw->X + rc.Left, objToDraw->Y + rc.Top,
+ &tempbmp, objToDraw->HasAlphaChannel(), kBlendMode_Alpha,
GfxDef::LegacyTrans255ToAlpha255(objToDraw->GetTransparency()));
}
diff --git a/engines/ags/shared/gui/gui_object.h b/engines/ags/shared/gui/gui_object.h
index 1e8381e2e5f..196918d7167 100644
--- a/engines/ags/shared/gui/gui_object.h
+++ b/engines/ags/shared/gui/gui_object.h
@@ -68,9 +68,9 @@ public:
// Operations
// Returns the (untransformed!) visual rectangle of this control,
- // optionally clipped by the logical position
+ // in *relative* coordinates, optionally clipped by the logical size
virtual Rect CalcGraphicRect(bool clipped) {
- return RectWH(X, Y, Width, Height);
+ return RectWH(0, 0, Width, Height);
}
virtual void Draw(Bitmap *ds, int x = 0, int y = 0) {
(void)ds; (void)x; (void)y;
diff --git a/engines/ags/shared/gui/gui_slider.cpp b/engines/ags/shared/gui/gui_slider.cpp
index db18d9f77db..1fcf6b491b1 100644
--- a/engines/ags/shared/gui/gui_slider.cpp
+++ b/engines/ags/shared/gui/gui_slider.cpp
@@ -65,9 +65,9 @@ Rect GUISlider::CalcGraphicRect(bool clipped) {
// Sliders are never clipped as of 3.6.0
// TODO: precalculate everything on width/height/graphic change!!
UpdateMetrics();
- Rect logical = RectWH(X, Y, Width, Height);
- Rect bar = Rect::MoveBy(_cachedBar, X, Y);
- Rect handle = Rect::MoveBy(_cachedHandle, X, Y);
+ Rect logical = RectWH(0, 0, Width, Height);
+ Rect bar = _cachedBar;
+ Rect handle = _cachedHandle;
return Rect(
std::min(std::min(logical.Left, bar.Left), handle.Left),
std::min(std::min(logical.Top, bar.Top), handle.Top),
Commit: 28a2b6aa9c1032bc27343eab763c2dd66998fc2a
https://github.com/scummvm/scummvm/commit/28a2b6aa9c1032bc27343eab763c2dd66998fc2a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:09-07:00
Commit Message:
AGS: Added extra checks for abort_engine being set
This fixes an intermittant error I noticed when
qutting QFG2AGDI via the quit dialog could open
the debugger with an error rather than exitting
Changed paths:
engines/ags/engine/ac/event.cpp
engines/ags/engine/script/script.cpp
diff --git a/engines/ags/engine/ac/event.cpp b/engines/ags/engine/ac/event.cpp
index 32049642c0b..4af03f3977a 100644
--- a/engines/ags/engine/ac/event.cpp
+++ b/engines/ags/engine/ac/event.cpp
@@ -325,9 +325,11 @@ void process_event(const EventHappened *evp) {
_G(gfxDriver)->DestroyDDB(ddb);
}
- } else if (evp->type == EV_IFACECLICK)
+ } else if (evp->type == EV_IFACECLICK) {
process_interface_click(evp->data1, evp->data2, evp->data3);
- else quit("process_event: unknown event to process");
+ } else {
+ quit("process_event: unknown event to process");
+ }
}
@@ -358,7 +360,7 @@ void processallevents() {
_G(inside_processevent)++;
- for (size_t i = 0; i < evtCopy->size(); ++i) {
+ for (size_t i = 0; i < evtCopy->size() && !_G(abort_engine); ++i) {
process_event(&(*evtCopy)[i]);
if (room_was != _GP(play).room_changes)
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index 3a25cb36f26..75dbe6a1a62 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -354,7 +354,7 @@ int RunScriptFunction(ccInstance *sci, const char *tsname, size_t numParam, cons
toret = _G(curscript)->inst->CallScriptFunction(tsname, numParam, params);
// 100 is if Aborted (eg. because we are LoadAGSGame'ing)
- if ((toret != 0) && (toret != -2) && (toret != 100)) {
+ if (!_G(abort_engine) && (toret != 0) && (toret != -2) && (toret != 100)) {
quit_with_script_error(tsname);
}
Commit: 63c42d42c377484bb25f908e7d5b8ecda41cec24
https://github.com/scummvm/scummvm/commit/63c42d42c377484bb25f908e7d5b8ecda41cec24
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:09-07:00
Commit Message:
AGS: Fixed ScriptString could be serialized with wrong length
>From upstream c00be4f9ee9501aebb0abc81ebbe5b4f2ffb0c0c
Changed paths:
engines/ags/engine/ac/dynobj/script_string.cpp
engines/ags/engine/ac/dynobj/script_string.h
engines/ags/engine/ac/string.cpp
diff --git a/engines/ags/engine/ac/dynobj/script_string.cpp b/engines/ags/engine/ac/dynobj/script_string.cpp
index d6c4d4da094..3e6bca65948 100644
--- a/engines/ags/engine/ac/dynobj/script_string.cpp
+++ b/engines/ags/engine/ac/dynobj/script_string.cpp
@@ -34,9 +34,9 @@ DynObjectRef ScriptString::CreateString(const char *fromText) {
int ScriptString::Dispose(const char *address, bool force) {
// always dispose
- if (text) {
- free(text);
- text = nullptr;
+ if (_text) {
+ free(_text);
+ _text = nullptr;
}
delete this;
return 1;
@@ -50,29 +50,34 @@ size_t ScriptString::CalcSerializeSize() {
return _len + 1 + sizeof(int32_t);
}
-void ScriptString::Serialize(const char *address, Stream *out) {
- const auto *cstr = text ? text : "";
+void ScriptString::Serialize(const char * /*address*/, Stream *out) {
+ const auto *cstr = _text ? _text : "";
out->WriteInt32(_len);
out->Write(cstr, _len + 1);
}
-void ScriptString::Unserialize(int index, Stream *in, size_t data_sz) {
+void ScriptString::Unserialize(int index, Stream *in, size_t /*data_sz*/) {
_len = in->ReadInt32();
- text = (char *)malloc(_len + 1);
- in->Read(text, _len + 1);
- text[_len] = 0; // for safety
- ccRegisterUnserializedObject(index, text, this);
+ _text = (char *)malloc(_len + 1);
+ in->Read(_text, _len + 1);
+ _text[_len] = 0; // for safety
+ ccRegisterUnserializedObject(index, _text, this);
}
-ScriptString::ScriptString() {
- text = nullptr;
- _len = 0;
+ScriptString::ScriptString(const char *text) {
+ _len = strlen(text);
+ _text = (char *)malloc(_len + 1);
+ memcpy(_text, text, _len + 1);
}
-ScriptString::ScriptString(const char *fromText) {
- _len = strlen(fromText);
- text = (char *)malloc(_len + 1);
- memcpy(text, fromText, _len + 1);
+ScriptString::ScriptString(char *text, bool take_ownership) {
+ _len = strlen(text);
+ if (take_ownership) {
+ _text = text;
+ } else {
+ _text = (char *)malloc(_len + 1);
+ memcpy(_text, text, _len + 1);
+ }
}
} // namespace AGS3
diff --git a/engines/ags/engine/ac/dynobj/script_string.h b/engines/ags/engine/ac/dynobj/script_string.h
index ae3406c4b76..4d6863d474a 100644
--- a/engines/ags/engine/ac/dynobj/script_string.h
+++ b/engines/ags/engine/ac/dynobj/script_string.h
@@ -27,18 +27,18 @@
namespace AGS3 {
struct ScriptString final : AGSCCDynamicObject, ICCStringClass {
- // TODO: the preallocated text buffer may be assigned externally;
- // find out if it's possible to refactor while keeping same functionality
- char *text;
-
int Dispose(const char *address, bool force) override;
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
DynObjectRef CreateString(const char *fromText) override;
- ScriptString();
- ScriptString(const char *fromText);
+ ScriptString() = default;
+ ScriptString(const char *text);
+ ScriptString(char *text, bool take_ownership);
+ char *GetTextPtr() const {
+ return _text;
+ }
protected:
// Calculate and return required space for serialization, in bytes
@@ -47,7 +47,10 @@ protected:
void Serialize(const char *address, AGS::Shared::Stream *out) override;
private:
- size_t _len;
+ // TODO: the preallocated text buffer may be assigned externally;
+ // find out if it's possible to refactor while keeping same functionality
+ char *_text = nullptr;
+ size_t _len = 0;
};
} // namespace AGS3
diff --git a/engines/ags/engine/ac/string.cpp b/engines/ags/engine/ac/string.cpp
index dc5dda16662..a2b5c7fc6b6 100644
--- a/engines/ags/engine/ac/string.cpp
+++ b/engines/ags/engine/ac/string.cpp
@@ -255,11 +255,10 @@ DynObjectRef CreateNewScriptStringObj(const char *fromText, bool reAllocate) {
ScriptString *str;
if (reAllocate) {
str = new ScriptString(fromText);
- } else {
- str = new ScriptString();
- str->text = const_cast<char *>(fromText);
+ } else { // TODO: refactor to avoid const casts!
+ str = new ScriptString((char *)fromText, true);
}
- void *obj_ptr = str->text;
+ void *obj_ptr = str->GetTextPtr();
int32_t handle = ccRegisterManagedObject(obj_ptr, str);
if (handle == 0) {
delete str;
Commit: 97c12e8435abdc5e51b390f07600b3c4bb0517c0
https://github.com/scummvm/scummvm/commit/97c12e8435abdc5e51b390f07600b3c4bb0517c0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:09-07:00
Commit Message:
AGS: Merged Character and ObjectCache structs, and hid in draw.cpp
>From upstream 753d47d975b10666702c47a22cbc4e68847787f1
Changed paths:
R engines/ags/engine/ac/character_cache.h
R engines/ags/engine/ac/object_cache.h
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/draw.h
engines/ags/engine/ac/drawing_surface.cpp
engines/ags/engine/ac/dynamic_sprite.cpp
engines/ags/engine/ac/game.cpp
engines/ags/engine/ac/global_object.cpp
engines/ags/engine/ac/object.cpp
engines/ags/engine/ac/room.cpp
engines/ags/engine/game/game_init.cpp
engines/ags/engine/main/engine.cpp
engines/ags/engine/main/game_file.cpp
engines/ags/globals.cpp
engines/ags/globals.h
engines/ags/plugins/ags_plugin.cpp
diff --git a/engines/ags/engine/ac/character_cache.h b/engines/ags/engine/ac/character_cache.h
deleted file mode 100644
index 925075542b1..00000000000
--- a/engines/ags/engine/ac/character_cache.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* 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_ENGINE_AC_CHARACTER_CACHE_H
-#define AGS_ENGINE_AC_CHARACTER_CACHE_H
-
-namespace AGS3 {
-
-namespace AGS {
-namespace Shared {
-class Bitmap;
-} // namespace Shared
-} // namespace AGS
-
-using namespace AGS; // FIXME later
-
-// stores cached info about the character
-struct CharacterCache {
- Shared::Bitmap *image = nullptr;
- int sppic = 0;
- int scaling = 0;
- int inUse = 0;
- short tintredwas = 0, tintgrnwas = 0, tintbluwas = 0, tintamntwas = 0;
- short lightlevwas = 0, tintlightwas = 0;
- // no mirroredWas is required, since the code inverts the sprite number
-};
-
-} // namespace AGS3
-
-#endif
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 696d988aa82..2416d54973a 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1,4 +1,4 @@
-/* ScummVM - Graphic Adventure Engine
+ /* 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
@@ -27,7 +27,6 @@
#include "ags/shared/util/compress.h"
#include "ags/shared/util/wgt2_allg.h"
#include "ags/shared/ac/view.h"
-#include "ags/engine/ac/character_cache.h"
#include "ags/engine/ac/character_extras.h"
#include "ags/shared/ac/character_info.h"
#include "ags/engine/ac/display.h"
@@ -42,7 +41,6 @@
#include "ags/engine/ac/gui.h"
#include "ags/engine/ac/mouse.h"
#include "ags/engine/ac/move_list.h"
-#include "ags/engine/ac/object_cache.h"
#include "ags/engine/ac/overlay.h"
#include "ags/engine/ac/sys_events.h"
#include "ags/engine/ac/room_object.h"
@@ -433,10 +431,10 @@ void dispose_room_drawdata() {
void clear_drawobj_cache() {
// clear the character cache
for (auto &cc : _GP(charcache)) {
- if (cc.inUse)
+ if (cc.in_use)
delete cc.image;
cc.image = nullptr;
- cc.inUse = 0;
+ cc.in_use = false;
}
// clear the object cache
@@ -600,7 +598,23 @@ void on_roomcamera_changed(Camera *cam) {
}
void mark_object_changed(int objid) {
- _G(objcache)[objid].ywas = -9999;
+ _G(objcache)[objid].y = -9999;
+}
+
+void reset_objcache_for_sprite(int sprnum) {
+ // Check if this sprite is assigned to any game object, and update them if necessary
+ // room objects cache
+ if (_G(croom) != nullptr) {
+ for (size_t i = 0; i < (size_t)_G(croom)->numobj; ++i) {
+ if (_G(objs)[i].num == sprnum)
+ _G(objcache)[i].sppic = -1;
+ }
+ }
+ // character cache
+ for (size_t i = 0; i < (size_t)_GP(game).numcharacters; ++i) {
+ if (_GP(charcache)[i].sppic == sprnum)
+ _GP(charcache)[i].sppic = -1;
+ }
}
void mark_screen_dirty() {
@@ -1201,14 +1215,14 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
(_G(objcache)[aa].sppic == _G(objs)[aa].num) &&
(actsp.Bmp != nullptr)) {
// HW acceleration
- _G(objcache)[aa].tintamntwas = tint_level;
- _G(objcache)[aa].tintredwas = tint_red;
- _G(objcache)[aa].tintgrnwas = tint_green;
- _G(objcache)[aa].tintbluwas = tint_blue;
- _G(objcache)[aa].tintlightwas = tint_light;
- _G(objcache)[aa].lightlevwas = light_level;
- _G(objcache)[aa].zoomWas = zoom_level;
- _G(objcache)[aa].mirroredWas = isMirrored;
+ _G(objcache)[aa].tintamnt = tint_level;
+ _G(objcache)[aa].tintr = tint_red;
+ _G(objcache)[aa].tintg = tint_green;
+ _G(objcache)[aa].tintb = tint_blue;
+ _G(objcache)[aa].tintlight = tint_light;
+ _G(objcache)[aa].lightlev = light_level;
+ _G(objcache)[aa].zoom = zoom_level;
+ _G(objcache)[aa].mirrored = isMirrored;
return 1;
}
@@ -1222,24 +1236,24 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
// If we have the image cached, use it
if ((_G(objcache)[aa].image != nullptr) &&
(_G(objcache)[aa].sppic == _G(objs)[aa].num) &&
- (_G(objcache)[aa].tintamntwas == tint_level) &&
- (_G(objcache)[aa].tintlightwas == tint_light) &&
- (_G(objcache)[aa].tintredwas == tint_red) &&
- (_G(objcache)[aa].tintgrnwas == tint_green) &&
- (_G(objcache)[aa].tintbluwas == tint_blue) &&
- (_G(objcache)[aa].lightlevwas == light_level) &&
- (_G(objcache)[aa].zoomWas == zoom_level) &&
- (_G(objcache)[aa].mirroredWas == isMirrored)) {
+ (_G(objcache)[aa].tintamnt == tint_level) &&
+ (_G(objcache)[aa].tintlight == tint_light) &&
+ (_G(objcache)[aa].tintr == tint_red) &&
+ (_G(objcache)[aa].tintg == tint_green) &&
+ (_G(objcache)[aa].tintb == tint_blue) &&
+ (_G(objcache)[aa].lightlev == light_level) &&
+ (_G(objcache)[aa].zoom == zoom_level) &&
+ (_G(objcache)[aa].mirrored == isMirrored)) {
// the image is the same, we can use it cached!
if ((_G(walkBehindMethod) != DrawOverCharSprite) &&
(actsp.Bmp != nullptr))
return 1;
// Check if the X & Y co-ords are the same, too -- if so, there
// is scope for further optimisations
- if ((_G(objcache)[aa].xwas == _G(objs)[aa].x) &&
- (_G(objcache)[aa].ywas == _G(objs)[aa].y) &&
- (actsp.Bmp != nullptr) &&
- (_G(walk_behind_baselines_changed) == 0))
+ 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;
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());
@@ -1278,14 +1292,14 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
// 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;
- _G(objcache)[aa].tintamntwas = tint_level;
- _G(objcache)[aa].tintredwas = tint_red;
- _G(objcache)[aa].tintgrnwas = tint_green;
- _G(objcache)[aa].tintbluwas = tint_blue;
- _G(objcache)[aa].tintlightwas = tint_light;
- _G(objcache)[aa].lightlevwas = light_level;
- _G(objcache)[aa].zoomWas = zoom_level;
- _G(objcache)[aa].mirroredWas = isMirrored;
+ _G(objcache)[aa].tintamnt = tint_level;
+ _G(objcache)[aa].tintr = tint_red;
+ _G(objcache)[aa].tintg = tint_green;
+ _G(objcache)[aa].tintb = tint_blue;
+ _G(objcache)[aa].tintlight = tint_light;
+ _G(objcache)[aa].lightlev = light_level;
+ _G(objcache)[aa].zoom = zoom_level;
+ _G(objcache)[aa].mirrored = isMirrored;
return 0;
}
@@ -1307,8 +1321,8 @@ void prepare_objects_for_drawing() {
auto &actsp = _GP(actsps)[useindx];
// update the cache for next time
- _G(objcache)[aa].xwas = _G(objs)[aa].x;
- _G(objcache)[aa].ywas = _G(objs)[aa].y;
+ _G(objcache)[aa].x = _G(objs)[aa].x;
+ _G(objcache)[aa].y = _G(objs)[aa].y;
int atxp = data_to_game_coord(_G(objs)[aa].x);
int atyp = data_to_game_coord(_G(objs)[aa].y) - tehHeight;
@@ -1328,19 +1342,19 @@ void prepare_objects_for_drawing() {
}
if (_G(gfxDriver)->HasAcceleratedTransform()) {
- actsp.Ddb->SetFlippedLeftRight(_G(objcache)[aa].mirroredWas != 0);
+ actsp.Ddb->SetFlippedLeftRight(_G(objcache)[aa].mirrored);
actsp.Ddb->SetStretch(_G(objs)[aa].last_width, _G(objs)[aa].last_height);
- actsp.Ddb->SetTint(_G(objcache)[aa].tintredwas, _G(objcache)[aa].tintgrnwas, _G(objcache)[aa].tintbluwas, (_G(objcache)[aa].tintamntwas * 256) / 100);
+ actsp.Ddb->SetTint(_G(objcache)[aa].tintr, _G(objcache)[aa].tintg, _G(objcache)[aa].tintb, (_G(objcache)[aa].tintamnt * 256) / 100);
- if (_G(objcache)[aa].tintamntwas > 0) {
- if (_G(objcache)[aa].tintlightwas == 0) // luminance of 0 -- pass 1 to enable
+ if (_G(objcache)[aa].tintamnt > 0) {
+ if (_G(objcache)[aa].tintlight == 0) // luminance of 0 -- pass 1 to enable
actsp.Ddb->SetLightLevel(1);
- else if (_G(objcache)[aa].tintlightwas < 250)
- actsp.Ddb->SetLightLevel(_G(objcache)[aa].tintlightwas);
+ else if (_G(objcache)[aa].tintlight < 250)
+ actsp.Ddb->SetLightLevel(_G(objcache)[aa].tintlight);
else
actsp.Ddb->SetLightLevel(0);
- } else if (_G(objcache)[aa].lightlevwas != 0)
- actsp.Ddb->SetLightLevel((_G(objcache)[aa].lightlevwas * 25) / 10 + 256);
+ } else if (_G(objcache)[aa].lightlev != 0)
+ actsp.Ddb->SetLightLevel((_G(objcache)[aa].lightlev * 25) / 10 + 256);
else
actsp.Ddb->SetLightLevel(0);
}
@@ -1494,27 +1508,27 @@ void prepare_characters_for_drawing() {
// if the character was the same sprite and scaling last time,
// just use the cached image
- if ((_GP(charcache)[aa].inUse) &&
- (_GP(charcache)[aa].sppic == specialpic) &&
- (_GP(charcache)[aa].scaling == zoom_level) &&
- (_GP(charcache)[aa].tintredwas == tint_red) &&
- (_GP(charcache)[aa].tintgrnwas == tint_green) &&
- (_GP(charcache)[aa].tintbluwas == tint_blue) &&
- (_GP(charcache)[aa].tintamntwas == tint_amount) &&
- (_GP(charcache)[aa].tintlightwas == tint_light) &&
- (_GP(charcache)[aa].lightlevwas == light_level)) {
+ if ((_GP(charcache)[aa].in_use) &&
+ (_GP(charcache)[aa].sppic == specialpic) &&
+ (_GP(charcache)[aa].zoom == zoom_level) &&
+ (_GP(charcache)[aa].tintr == tint_red) &&
+ (_GP(charcache)[aa].tintg == tint_green) &&
+ (_GP(charcache)[aa].tintb == tint_blue) &&
+ (_GP(charcache)[aa].tintamnt == tint_amount) &&
+ (_GP(charcache)[aa].tintlight == tint_light) &&
+ (_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);
} else {
usingCachedImage = true;
}
- } else if ((_GP(charcache)[aa].inUse) &&
- (_GP(charcache)[aa].sppic == specialpic) &&
- (_G(gfxDriver)->HasAcceleratedTransform())) {
+ } else if ((_GP(charcache)[aa].in_use) &&
+ (_GP(charcache)[aa].sppic == specialpic) &&
+ (_G(gfxDriver)->HasAcceleratedTransform())) {
usingCachedImage = true;
- } else if (_GP(charcache)[aa].inUse) {
- _GP(charcache)[aa].inUse = 0;
+ } else if (_GP(charcache)[aa].in_use) {
+ _GP(charcache)[aa].in_use = false;
}
_G(our_eip) = 3332;
@@ -1545,17 +1559,17 @@ void prepare_characters_for_drawing() {
// adjust the Y positioning for the character's Z co-ord
- data_to_game_coord(chin->z);
- _GP(charcache)[aa].scaling = zoom_level;
+ _GP(charcache)[aa].zoom = zoom_level;
_GP(charcache)[aa].sppic = specialpic;
- _GP(charcache)[aa].tintredwas = tint_red;
- _GP(charcache)[aa].tintgrnwas = tint_green;
- _GP(charcache)[aa].tintbluwas = tint_blue;
- _GP(charcache)[aa].tintamntwas = tint_amount;
- _GP(charcache)[aa].tintlightwas = tint_light;
- _GP(charcache)[aa].lightlevwas = light_level;
+ _GP(charcache)[aa].tintr = tint_red;
+ _GP(charcache)[aa].tintg = tint_green;
+ _GP(charcache)[aa].tintb = tint_blue;
+ _GP(charcache)[aa].tintamnt = tint_amount;
+ _GP(charcache)[aa].tintlight = tint_light;
+ _GP(charcache)[aa].lightlev = light_level;
// If cache needs to be re-drawn
- if (!_GP(charcache)[aa].inUse) {
+ if (!_GP(charcache)[aa].in_use) {
// create the base sprite in _GP(actsps)[useindx], which will
// be scaled and/or flipped, as appropriate
@@ -1587,7 +1601,7 @@ void prepare_characters_for_drawing() {
}
// update the character cache with the new image
- _GP(charcache)[aa].inUse = 1;
+ _GP(charcache)[aa].in_use = true;
_GP(charcache)[aa].image = recycle_bitmap(_GP(charcache)[aa].image, coldept, actsp.Bmp->GetWidth(), actsp.Bmp->GetHeight());
_GP(charcache)[aa].image->Blit(actsp.Bmp.get(), 0, 0);
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index 599ea9e4b38..c0bd6390e9f 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -84,6 +84,18 @@ struct ObjTexture {
ObjTexture &operator =(ObjTexture &&o);
};
+// ObjectCache stores cached object data, used to determine
+// if active sprite / texture should be reconstructed
+struct ObjectCache {
+ Shared::Bitmap *image = nullptr;
+ bool in_use = false;
+ int sppic = 0;
+ short tintr = 0, tintg = 0, tintb = 0, tintamnt = 0, tintlight = 0;
+ short lightlev = 0, zoom = 0;
+ bool mirrored = 0;
+ int x = 0, y = 0;
+};
+
// Converts AGS color index to the actual bitmap color using game's color depth
int MakeColor(int color_index);
@@ -116,8 +128,10 @@ void on_roomviewport_changed(Viewport *view);
void detect_roomviewport_overlaps(size_t z_index);
// Updates drawing settings if room camera's size has changed
void on_roomcamera_changed(Camera *cam);
-// Marks particular object as need too update the texture
+// Marks particular object as need to update the texture
void mark_object_changed(int objid);
+// Resets all object caches which reference this sprite
+void reset_objcache_for_sprite(int sprnum);
// whether there are currently remnants of a DisplaySpeech
void mark_screen_dirty();
diff --git a/engines/ags/engine/ac/drawing_surface.cpp b/engines/ags/engine/ac/drawing_surface.cpp
index 14355bccaaf..0484e87d09e 100644
--- a/engines/ags/engine/ac/drawing_surface.cpp
+++ b/engines/ags/engine/ac/drawing_surface.cpp
@@ -22,13 +22,11 @@
#include "ags/engine/ac/draw.h"
#include "ags/engine/ac/drawing_surface.h"
#include "ags/shared/ac/common.h"
-#include "ags/engine/ac/character_cache.h"
#include "ags/engine/ac/display.h"
#include "ags/engine/ac/game.h"
#include "ags/shared/ac/game_setup_struct.h"
#include "ags/engine/ac/game_state.h"
#include "ags/engine/ac/global_translation.h"
-#include "ags/engine/ac/object_cache.h"
#include "ags/engine/ac/room_object.h"
#include "ags/engine/ac/room_status.h"
#include "ags/engine/ac/string.h"
diff --git a/engines/ags/engine/ac/dynamic_sprite.cpp b/engines/ags/engine/ac/dynamic_sprite.cpp
index de63ee39363..e6b3532bf17 100644
--- a/engines/ags/engine/ac/dynamic_sprite.cpp
+++ b/engines/ags/engine/ac/dynamic_sprite.cpp
@@ -22,7 +22,6 @@
#include "ags/lib/std/math.h"
#include "ags/engine/ac/dynamic_sprite.h"
#include "ags/shared/ac/common.h"
-#include "ags/engine/ac/character_cache.h"
#include "ags/engine/ac/draw.h"
#include "ags/engine/ac/game.h"
#include "ags/shared/ac/game_setup_struct.h"
@@ -30,7 +29,6 @@
#include "ags/engine/ac/global_dynamic_sprite.h"
#include "ags/engine/ac/global_game.h"
#include "ags/engine/ac/math.h" // M_PI
-#include "ags/engine/ac/object_cache.h"
#include "ags/engine/ac/path_helper.h"
#include "ags/engine/ac/room_object.h"
#include "ags/engine/ac/room_status.h"
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index ac08772fc9f..3fcb319b723 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -26,7 +26,6 @@
#include "ags/engine/ac/audio_channel.h"
#include "ags/engine/ac/button.h"
#include "ags/engine/ac/character.h"
-#include "ags/engine/ac/character_cache.h"
#include "ags/shared/ac/dialog_topic.h"
#include "ags/engine/ac/draw.h"
#include "ags/engine/ac/dynamic_sprite.h"
@@ -46,7 +45,6 @@
#include "ags/engine/ac/lip_sync.h"
#include "ags/engine/ac/mouse.h"
#include "ags/engine/ac/move_list.h"
-#include "ags/engine/ac/object_cache.h"
#include "ags/engine/ac/overlay.h"
#include "ags/engine/ac/path_helper.h"
#include "ags/engine/ac/sys_events.h"
@@ -1342,19 +1340,9 @@ bool unserialize_audio_script_object(int index, const char *objectType, Stream *
}
void game_sprite_updated(int sprnum) {
- // Check if this sprite is assigned to any game object, and update them if necessary
- // room objects cache
- if (_G(croom) != nullptr) {
- for (size_t i = 0; i < (size_t)_G(croom)->numobj; ++i) {
- if (_G(objs)[i].num == sprnum)
- _G(objcache)[i].sppic = -1;
- }
- }
- // character cache
- for (size_t i = 0; i < (size_t)_GP(game).numcharacters; ++i) {
- if (_GP(charcache)[i].sppic == sprnum)
- _GP(charcache)[i].sppic = -1;
- }
+ // character and object draw caches
+ reset_objcache_for_sprite(sprnum);
+
// gui backgrounds
for (size_t i = 0; i < (size_t)_GP(game).numgui; ++i) {
if (_GP(guis)[i].BgImage == sprnum) {
@@ -1376,21 +1364,15 @@ void game_sprite_updated(int sprnum) {
}
void game_sprite_deleted(int sprnum) {
- // Check if this sprite is assigned to any game object, and update them if necessary
- // room objects and their cache
+ // character and object draw caches
+ reset_objcache_for_sprite(sprnum);
+ // room object graphics
if (_G(croom) != nullptr) {
for (size_t i = 0; i < (size_t)_G(croom)->numobj; ++i) {
- if (_G(objs)[i].num == sprnum) {
+ if (_G(objs)[i].num == sprnum)
_G(objs)[i].num = 0;
- _G(objcache)[i].sppic = -1;
- }
}
}
- // character cache
- for (size_t i = 0; i < (size_t)_GP(game).numcharacters; ++i) {
- if (_GP(charcache)[i].sppic == sprnum)
- _GP(charcache)[i].sppic = -1;
- }
// gui backgrounds
for (size_t i = 0; i < (size_t)_GP(game).numgui; ++i) {
if (_GP(guis)[i].BgImage == sprnum) {
diff --git a/engines/ags/engine/ac/global_object.cpp b/engines/ags/engine/ac/global_object.cpp
index a7067fc827d..9c2eb1caf95 100644
--- a/engines/ags/engine/ac/global_object.cpp
+++ b/engines/ags/engine/ac/global_object.cpp
@@ -31,7 +31,6 @@
#include "ags/engine/ac/global_character.h"
#include "ags/engine/ac/global_translation.h"
#include "ags/engine/ac/object.h"
-#include "ags/engine/ac/object_cache.h"
#include "ags/engine/ac/properties.h"
#include "ags/engine/ac/room_object.h"
#include "ags/engine/ac/room_status.h"
diff --git a/engines/ags/engine/ac/object.cpp b/engines/ags/engine/ac/object.cpp
index e22ba59d883..cf731e84a10 100644
--- a/engines/ags/engine/ac/object.cpp
+++ b/engines/ags/engine/ac/object.cpp
@@ -27,7 +27,6 @@
#include "ags/engine/ac/game_state.h"
#include "ags/engine/ac/global_object.h"
#include "ags/engine/ac/global_translation.h"
-#include "ags/engine/ac/object_cache.h"
#include "ags/engine/ac/properties.h"
#include "ags/engine/ac/room.h"
#include "ags/engine/ac/room_status.h"
diff --git a/engines/ags/engine/ac/object_cache.h b/engines/ags/engine/ac/object_cache.h
deleted file mode 100644
index c0c09cc845d..00000000000
--- a/engines/ags/engine/ac/object_cache.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 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_ENGINE_AC_OBJECT_CACHE_H
-#define AGS_ENGINE_AC_OBJECT_CACHE_H
-
-namespace AGS3 {
-
-// stores cached object info
-struct ObjectCache {
- Shared::Bitmap *image = nullptr;
- int sppic = 0;
- short tintredwas = 0, tintgrnwas = 0, tintbluwas = 0;
- short tintamntwas = 0, tintlightwas = 0;
- short lightlevwas = 0, zoomWas = 0;
- bool mirroredWas = false;
-
- // The following are used to determine if the character has moved
- int xwas = 0, ywas = 0;
-};
-
-} // namespace AGS3
-
-#endif
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 8554a637956..cb4be1cc741 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -23,7 +23,6 @@
#include "ags/shared/util/string_utils.h" //strlwr()
#include "ags/shared/ac/common.h"
#include "ags/engine/ac/character.h"
-#include "ags/engine/ac/character_cache.h"
#include "ags/engine/ac/character_extras.h"
#include "ags/engine/ac/draw.h"
#include "ags/engine/ac/event.h"
@@ -38,7 +37,6 @@
#include "ags/engine/ac/global_translation.h"
#include "ags/engine/ac/move_list.h"
#include "ags/engine/ac/mouse.h"
-#include "ags/engine/ac/object_cache.h"
#include "ags/engine/ac/overlay.h"
#include "ags/engine/ac/properties.h"
#include "ags/engine/ac/region.h"
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index 83add8905eb..7462af2625a 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -20,7 +20,6 @@
*/
#include "ags/engine/ac/character.h"
-#include "ags/engine/ac/character_cache.h"
#include "ags/engine/ac/dialog.h"
#include "ags/engine/ac/display.h"
#include "ags/engine/ac/draw.h"
diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index 2e78e61c113..20ea7e1420e 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -39,7 +39,6 @@
#include "ags/engine/ac/global_game.h"
#include "ags/engine/ac/gui.h"
#include "ags/engine/ac/lip_sync.h"
-#include "ags/engine/ac/object_cache.h"
#include "ags/engine/ac/path_helper.h"
#include "ags/engine/ac/route_finder.h"
#include "ags/engine/ac/sys_events.h"
diff --git a/engines/ags/engine/main/game_file.cpp b/engines/ags/engine/main/game_file.cpp
index a61aea73b05..adcd62429e9 100644
--- a/engines/ags/engine/main/game_file.cpp
+++ b/engines/ags/engine/main/game_file.cpp
@@ -25,7 +25,6 @@
#include "ags/shared/ac/common.h"
#include "ags/engine/ac/character.h"
-#include "ags/engine/ac/character_cache.h"
#include "ags/shared/ac/dialog_topic.h"
#include "ags/engine/ac/draw.h"
#include "ags/engine/ac/game.h"
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 0abe5bf48ec..23ac78fb66b 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -38,7 +38,6 @@
#include "ags/shared/gui/gui_textbox.h"
#include "ags/shared/script/cc_common.h"
#include "ags/shared/util/directory.h"
-#include "ags/engine/ac/character_cache.h"
#include "ags/engine/ac/character_extras.h"
#include "ags/engine/ac/draw.h"
#include "ags/engine/ac/draw_software.h"
@@ -47,7 +46,6 @@
#include "ags/engine/ac/game_state.h"
#include "ags/engine/ac/mouse.h"
#include "ags/engine/ac/move_list.h"
-#include "ags/engine/ac/object_cache.h"
#include "ags/engine/ac/room_status.h"
#include "ags/engine/ac/route_finder_jps.h"
#include "ags/engine/ac/screen_overlay.h"
@@ -238,7 +236,7 @@ Globals::Globals() {
_scrHotspot = new ScriptHotspot[MAX_ROOM_HOTSPOTS];
_scrRegion = new ScriptRegion[MAX_ROOM_REGIONS];
_scrInv = new ScriptInvItem[MAX_INV];
- _charcache = new std::vector<CharacterCache>();
+ _charcache = new std::vector<ObjectCache>();
_objcache = new ObjectCache[MAX_ROOM_OBJECTS];
_charextra = new std::vector<CharacterExtras>();
_mls = new std::vector<MoveList>();
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 1919d4c2fee..0077f314ac8 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -752,7 +752,7 @@ public:
std::vector<ViewStruct> *_views;
// Cached character and object states, used to determine
// whether these require texture update
- std::vector<CharacterCache> *_charcache;
+ std::vector<ObjectCache> *_charcache;
ObjectCache *_objcache;
std::vector<CharacterExtras> *_charextra;
std::vector<MoveList> *_mls;
diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index 9f978835def..29ef42dab91 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -26,7 +26,6 @@
#include "ags/plugins/core/core.h"
#include "ags/shared/ac/common.h"
#include "ags/shared/ac/view.h"
-#include "ags/engine/ac/character_cache.h"
#include "ags/engine/ac/display.h"
#include "ags/engine/ac/draw.h"
#include "ags/engine/ac/dynamic_sprite.h"
@@ -39,7 +38,6 @@
#include "ags/shared/ac/keycode.h"
#include "ags/engine/ac/mouse.h"
#include "ags/engine/ac/move_list.h"
-#include "ags/engine/ac/object_cache.h"
#include "ags/engine/ac/parser.h"
#include "ags/engine/ac/path_helper.h"
#include "ags/engine/ac/room_status.h"
Commit: 84a39254429a293bfd959a731d643c5ee407ba27
https://github.com/scummvm/scummvm/commit/84a39254429a293bfd959a731d643c5ee407ba27
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:09-07:00
Commit Message:
AGS: Simplified the use of get_overlay_position()
>From upstream d673fb3822907fd01bf0e2c6f98bee04a8a5b17b
Changed paths:
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/overlay.cpp
engines/ags/engine/ac/overlay.h
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 2416d54973a..5e7d2fd5eb1 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1876,9 +1876,8 @@ void draw_gui_and_overlays() {
over.ddb->SetStretch(over.scaleWidth, over.scaleHeight);
over.ddb->SetAlpha(GfxDef::LegacyTrans255ToAlpha255(over.transparency));
- int tdxp, tdyp;
- get_overlay_position(over, &tdxp, &tdyp);
- add_to_sprite_list(over.ddb, tdxp, tdyp, over.zorder, false, -1);
+ Point pos = get_overlay_position(over);
+ add_to_sprite_list(over.ddb, pos.X, pos.Y, over.zorder, false);
}
// Add GUIs
diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index 5ddb24a4f96..868809b7ba1 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "ags/lib/std/algorithm.h"
#include "ags/engine/ac/overlay.h"
#include "ags/shared/ac/common.h"
#include "ags/shared/ac/view.h"
@@ -70,10 +71,8 @@ int Overlay_GetX(ScriptOverlay *scover) {
if (ovri < 0)
quit("!invalid overlay ID specified");
- int tdxp, tdyp;
- get_overlay_position(_GP(screenover)[ovri], &tdxp, &tdyp);
-
- return game_to_data_coord(tdxp);
+ Point pos = get_overlay_position(_GP(screenover)[ovri]);
+ return game_to_data_coord(pos.X);
}
void Overlay_SetX(ScriptOverlay *scover, int newx) {
@@ -89,10 +88,8 @@ int Overlay_GetY(ScriptOverlay *scover) {
if (ovri < 0)
quit("!invalid overlay ID specified");
- int tdxp, tdyp;
- get_overlay_position(_GP(screenover)[ovri], &tdxp, &tdyp);
-
- return game_to_data_coord(tdyp);
+ Point pos = get_overlay_position(_GP(screenover)[ovri]);
+ return game_to_data_coord(pos.Y);
}
void Overlay_SetY(ScriptOverlay *scover, int newy) {
@@ -347,11 +344,9 @@ size_t add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, int pic
return _GP(screenover).size() - 1;
}
-void get_overlay_position(const ScreenOverlay &over, int *x, int *y) {
- int tdxp, tdyp;
- const Rect &ui_view = _GP(play).GetUIViewport();
-
+Point get_overlay_position(const ScreenOverlay &over) {
if (over.x == OVR_AUTOPLACE) {
+ const Rect &ui_view = _GP(play).GetUIViewport();
// auto place on character
int charid = over.y;
@@ -359,13 +354,12 @@ void get_overlay_position(const ScreenOverlay &over, int *x, int *y) {
const int charpic = _GP(views)[_GP(game).chars[charid].view].loops[_GP(game).chars[charid].loop].frames[0].pic;
const int height = (_GP(charextra)[charid].height < 1) ? _GP(game).SpriteInfos[charpic].Height : _GP(charextra)[charid].height;
Point screenpt = view->RoomToScreen(
- data_to_game_coord(_GP(game).chars[charid].x),
- data_to_game_coord(_GP(game).chars[charid].get_effective_y()) - height).first;
- tdxp = screenpt.X - over.pic->GetWidth() / 2;
- if (tdxp < 0) tdxp = 0;
- tdyp = screenpt.Y - get_fixed_pixel_size(5);
+ data_to_game_coord(_GP(game).chars[charid].x),
+ data_to_game_coord(_GP(game).chars[charid].get_effective_y()) - height).first;
+ int tdxp = std::max(0, screenpt.X - over.pic->GetWidth() / 2);
+ int tdyp = screenpt.Y - get_fixed_pixel_size(5);
tdyp -= over.pic->GetHeight();
- if (tdyp < 5) tdyp = 5;
+ tdyp = std::max(5, tdyp);
if ((tdxp + over.pic->GetWidth()) >= ui_view.GetWidth())
tdxp = (ui_view.GetWidth() - over.pic->GetWidth()) - 1;
@@ -373,20 +367,16 @@ void get_overlay_position(const ScreenOverlay &over, int *x, int *y) {
tdxp = ui_view.GetWidth() / 2 - over.pic->GetWidth() / 2;
tdyp = ui_view.GetHeight() / 2 - over.pic->GetHeight() / 2;
}
+ return Point(tdxp, tdyp);
} else {
// Note: the internal offset is only needed when x,y coordinates are specified
// and only in the case where the overlay is using a GUI. See issue #1098
- tdxp = over.x + over.offsetX;
- tdyp = over.y + over.offsetY;
-
- if (!over.positionRelativeToScreen) {
- Point tdxy = _GP(play).RoomToScreen(tdxp, tdyp);
- tdxp = tdxy.X;
- tdyp = tdxy.Y;
- }
+ int tdxp = over.x + over.offsetX;
+ int tdyp = over.y + over.offsetY;
+ if (over.positionRelativeToScreen)
+ return Point(tdxp, tdyp);
+ return _GP(play).RoomToScreen(tdxp, tdyp);
}
- *x = tdxp;
- *y = tdyp;
}
void recreate_overlay_ddbs() {
diff --git a/engines/ags/engine/ac/overlay.h b/engines/ags/engine/ac/overlay.h
index bd7f07bb72d..40c640eab09 100644
--- a/engines/ags/engine/ac/overlay.h
+++ b/engines/ags/engine/ac/overlay.h
@@ -22,6 +22,7 @@
#ifndef AGS_ENGINE_AC_OVERLAY_H
#define AGS_ENGINE_AC_OVERLAY_H
+#include "ags/shared/util/geometry.h"
#include "ags/engine/ac/screen_overlay.h"
#include "ags/engine/ac/dynobj/script_overlay.h"
@@ -48,7 +49,7 @@ ScriptOverlay *Overlay_CreateTextual(int x, int y, int width, int font, int colo
int find_overlay_of_type(int type);
void remove_screen_overlay(int type);
// Calculates overlay position in screen coordinates
-void get_overlay_position(const ScreenOverlay &over, int *x, int *y);
+Point get_overlay_position(const ScreenOverlay &over);
size_t add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, bool alphaChannel = false);
size_t add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, int pic_offx, int pic_offy, bool alphaChannel = false);
void remove_screen_overlay_index(size_t over_idx);
Commit: b1649597d7bc5243e3b4fcd425551e2e24ed71a4
https://github.com/scummvm/scummvm/commit/b1649597d7bc5243e3b4fcd425551e2e24ed71a4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:10-07:00
Commit Message:
AGS: Replaced Math/std Min/Max with ScummVM macros
Inspired by 6dee5ee6f271c600e30879d892295ea6069e8cc9
Changed paths:
engines/ags/engine/ac/display.cpp
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/file.cpp
engines/ags/engine/ac/inv_window.cpp
engines/ags/engine/ac/overlay.cpp
engines/ags/engine/ac/route_finder_impl.cpp
engines/ags/engine/ac/string.cpp
engines/ags/engine/ac/walk_behind.cpp
engines/ags/engine/device/mouse_w32.cpp
engines/ags/engine/game/savegame.cpp
engines/ags/engine/gfx/ali_3d_scummvm.cpp
engines/ags/engine/main/engine_setup.cpp
engines/ags/engine/main/graphics_mode.cpp
engines/ags/engine/platform/base/ags_platform_driver.cpp
engines/ags/engine/script/cc_instance.cpp
engines/ags/engine/script/script_api.cpp
engines/ags/shared/ac/game_setup_struct.cpp
engines/ags/shared/ac/sprite_file.cpp
engines/ags/shared/ac/words_dictionary.cpp
engines/ags/shared/font/fonts.cpp
engines/ags/shared/game/interactions.cpp
engines/ags/shared/game/main_game_file.cpp
engines/ags/shared/gui/gui_label.cpp
engines/ags/shared/gui/gui_listbox.cpp
engines/ags/shared/gui/gui_slider.cpp
engines/ags/shared/util/aligned_stream.cpp
engines/ags/shared/util/buffered_stream.cpp
engines/ags/shared/util/geometry.cpp
engines/ags/shared/util/memory.h
engines/ags/shared/util/memory_stream.cpp
engines/ags/shared/util/string.cpp
engines/ags/shared/util/string_utils.cpp
engines/ags/shared/util/text_stream_reader.cpp
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index 442044ba925..43365732cf6 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -174,8 +174,8 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
if (disp_type < DISPLAYTEXT_NORMALOVERLAY)
remove_screen_overlay(_GP(play).text_overlay_on); // remove any previous blocking texts
- const int bmp_width = std::max(2, wii);
- const int bmp_height = std::max(2, disp.fulltxtheight + extraHeight);
+ const int bmp_width = MAX(2, wii);
+ const int bmp_height = MAX(2, disp.fulltxtheight + extraHeight);
Bitmap *text_window_ds = BitmapHelper::CreateTransparentBitmap(
bmp_width, bmp_height, _GP(game).GetColorDepth());
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 5e7d2fd5eb1..23af33e5e95 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -299,8 +299,8 @@ AGS_INLINE void ctx_data_to_game_coord(int &x, int &y, bool hires_ctx) {
AGS_INLINE void ctx_data_to_game_size(int &w, int &h, bool hires_ctx) {
if (hires_ctx && !_GP(game).IsLegacyHiRes()) {
- w = Math::Max(1, (w / HIRES_COORD_MULTIPLIER));
- h = Math::Max(1, (h / HIRES_COORD_MULTIPLIER));
+ w = MAX(1, (w / HIRES_COORD_MULTIPLIER));
+ h = MAX(1, (h / HIRES_COORD_MULTIPLIER));
} else if (!hires_ctx && _GP(game).IsLegacyHiRes()) {
w *= HIRES_COORD_MULTIPLIER;
h *= HIRES_COORD_MULTIPLIER;
@@ -309,7 +309,7 @@ AGS_INLINE void ctx_data_to_game_size(int &w, int &h, bool hires_ctx) {
AGS_INLINE int ctx_data_to_game_size(int size, bool hires_ctx) {
if (hires_ctx && !_GP(game).IsLegacyHiRes())
- return Math::Max(1, (size / HIRES_COORD_MULTIPLIER));
+ return MAX(1, (size / HIRES_COORD_MULTIPLIER));
if (!hires_ctx && _GP(game).IsLegacyHiRes())
return size * HIRES_COORD_MULTIPLIER;
return size;
@@ -319,7 +319,7 @@ AGS_INLINE int game_to_ctx_data_size(int size, bool hires_ctx) {
if (hires_ctx && !_GP(game).IsLegacyHiRes())
return size * HIRES_COORD_MULTIPLIER;
else if (!hires_ctx && _GP(game).IsLegacyHiRes())
- return Math::Max(1, (size / HIRES_COORD_MULTIPLIER));
+ return MAX(1, (size / HIRES_COORD_MULTIPLIER));
return size;
}
diff --git a/engines/ags/engine/ac/file.cpp b/engines/ags/engine/ac/file.cpp
index 3fcf581d0b2..306386f9028 100644
--- a/engines/ags/engine/ac/file.cpp
+++ b/engines/ags/engine/ac/file.cpp
@@ -466,7 +466,7 @@ static int ags_pf_ungetc(int /*c*/, void * /*userdata*/) {
static long ags_pf_fread(void *p, long n, void *userdata) {
AGS_PACKFILE_OBJ *obj = (AGS_PACKFILE_OBJ *)userdata;
if (obj->remains > 0) {
- size_t read = Math::Min(obj->remains, (size_t)n);
+ size_t read = MIN(obj->remains, (size_t)n);
obj->remains -= read;
return obj->stream->Read(p, read);
}
diff --git a/engines/ags/engine/ac/inv_window.cpp b/engines/ags/engine/ac/inv_window.cpp
index c383fc5751e..d7fd0ea1a12 100644
--- a/engines/ags/engine/ac/inv_window.cpp
+++ b/engines/ags/engine/ac/inv_window.cpp
@@ -303,7 +303,7 @@ void InventoryScreen::Draw(Bitmap *ds) {
wputblock(ds, barxp + 1 + ((i - top_item) % 4) * widest + widest / 2 - spof->GetWidth() / 2,
bartop + 1 + ((i - top_item) / 4) * highest + highest / 2 - spof->GetHeight() / 2, spof, 1);
}
-#define BUTTONWID Math::Max(1, _GP(game).SpriteInfos[btn_select_sprite].Width)
+#define BUTTONWID MAX(1, _GP(game).SpriteInfos[btn_select_sprite].Width)
// Draw select, look and OK buttons
wputblock(ds, 2, buttonyp + get_fixed_pixel_size(2), _GP(spriteset)[btn_look_sprite], 1);
wputblock(ds, 3 + BUTTONWID, buttonyp + get_fixed_pixel_size(2), _GP(spriteset)[btn_select_sprite], 1);
diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index 868809b7ba1..afeb63445fb 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -356,10 +356,10 @@ Point get_overlay_position(const ScreenOverlay &over) {
Point screenpt = view->RoomToScreen(
data_to_game_coord(_GP(game).chars[charid].x),
data_to_game_coord(_GP(game).chars[charid].get_effective_y()) - height).first;
- int tdxp = std::max(0, screenpt.X - over.pic->GetWidth() / 2);
+ int tdxp = MAX(0, screenpt.X - over.pic->GetWidth() / 2);
int tdyp = screenpt.Y - get_fixed_pixel_size(5);
tdyp -= over.pic->GetHeight();
- tdyp = std::max(5, tdyp);
+ tdyp = MAX(5, tdyp);
if ((tdxp + over.pic->GetWidth()) >= ui_view.GetWidth())
tdxp = (ui_view.GetWidth() - over.pic->GetWidth()) - 1;
diff --git a/engines/ags/engine/ac/route_finder_impl.cpp b/engines/ags/engine/ac/route_finder_impl.cpp
index faea6490527..27c29ed0f89 100644
--- a/engines/ags/engine/ac/route_finder_impl.cpp
+++ b/engines/ags/engine/ac/route_finder_impl.cpp
@@ -96,7 +96,7 @@ static int find_route_jps(int fromx, int fromy, int destx, int desty) {
_G(num_navpoints) = 0;
// new behavior: cut path if too complex rather than abort with error message
- int count = std::min<int>((int)cpath.size(), MAXNAVPOINTS);
+ int count = MIN<int>((int)cpath.size(), MAXNAVPOINTS);
for (int i = 0; i < count; i++) {
int x, y;
diff --git a/engines/ags/engine/ac/string.cpp b/engines/ags/engine/ac/string.cpp
index a2b5c7fc6b6..5dbac47218d 100644
--- a/engines/ags/engine/ac/string.cpp
+++ b/engines/ags/engine/ac/string.cpp
@@ -114,7 +114,7 @@ const char *String_Substring(const char *thisString, int index, int length) {
size_t strlen = ustrlen(thisString);
if ((index < 0) || ((size_t)index > strlen))
quit("!String.Substring: invalid index");
- size_t sublen = std::min((size_t)length, strlen - index);
+ size_t sublen = MIN((size_t)length, strlen - index);
size_t start = uoffset(thisString, index);
size_t end = uoffset(thisString + start, sublen) + start;
size_t copysz = end - start;
diff --git a/engines/ags/engine/ac/walk_behind.cpp b/engines/ags/engine/ac/walk_behind.cpp
index 62e5f73cdb3..9c64a1466de 100644
--- a/engines/ags/engine/ac/walk_behind.cpp
+++ b/engines/ags/engine/ac/walk_behind.cpp
@@ -104,7 +104,7 @@ bool walkbehinds_cropout(Bitmap *sprit, int sprx, int spry, int basel, int zoom)
bool pixels_changed = false;
// pass along the sprite's pixels, but skip those that lie outside the mask
- for (int x = std::max(0, 0 - sprx);
+ for (int x = MAX(0, 0 - sprx);
(x < sprit->GetWidth()) && (x + sprx < _GP(thisroom).WalkBehindMask->GetWidth()); ++x) {
// select the WB column at this x
const auto &wbcol = walkBehindCols[x + sprx];
@@ -116,7 +116,7 @@ bool walkbehinds_cropout(Bitmap *sprit, int sprx, int spry, int basel, int zoom)
// ensure we only check within the valid areas (between Y1 and Y2)
// we assume that Y1 and Y2 are always within the mask
- for (int y = std::max(0, wbcol.Y1 - spry);
+ for (int y = MAX(0, wbcol.Y1 - spry);
(y < sprit->GetHeight()) && (y + spry < wbcol.Y2); ++y) {
const int wb = _GP(thisroom).WalkBehindMask->GetScanLine(y + spry)[x + sprx];
if (wb < 1) continue; // "no area"
@@ -167,10 +167,10 @@ void walkbehinds_recalc() {
}
wbcol.Y2 = y + 1; // +1 to allow bottom line of screen to work (CHECKME??)
// resize the bounding rect
- walkBehindAABB[wb].Left = std::min(col, walkBehindAABB[wb].Left);
- walkBehindAABB[wb].Top = std::min(y, walkBehindAABB[wb].Top);
- walkBehindAABB[wb].Right = std::max(col, walkBehindAABB[wb].Right);
- walkBehindAABB[wb].Bottom = std::max(y, walkBehindAABB[wb].Bottom);
+ walkBehindAABB[wb].Left = MIN(col, walkBehindAABB[wb].Left);
+ walkBehindAABB[wb].Top = MIN(y, walkBehindAABB[wb].Top);
+ walkBehindAABB[wb].Right = MAX(col, walkBehindAABB[wb].Right);
+ walkBehindAABB[wb].Bottom = MAX(y, walkBehindAABB[wb].Bottom);
}
}
}
diff --git a/engines/ags/engine/device/mouse_w32.cpp b/engines/ags/engine/device/mouse_w32.cpp
index 229d93b0ab2..016a00a2cb3 100644
--- a/engines/ags/engine/device/mouse_w32.cpp
+++ b/engines/ags/engine/device/mouse_w32.cpp
@@ -160,7 +160,7 @@ float Mouse::GetSpeedUnit() {
}
void Mouse::SetSpeed(float speed) {
- SpeedVal = Math::Max(0.f, speed);
+ SpeedVal = MAX(0.f, speed);
Speed = SpeedUnit * SpeedVal;
}
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index e05bf43b694..b2dfc689ded 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -446,7 +446,7 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
RemapLegacySoundNums(_GP(game), _GP(views), _G(loaded_game_file_version));
// restore these to the ones retrieved from the save game
- const size_t dynsurf_num = Math::Min((uint)MAX_DYNAMIC_SURFACES, r_data.DynamicSurfaces.size());
+ const size_t dynsurf_num = MIN((uint)MAX_DYNAMIC_SURFACES, r_data.DynamicSurfaces.size());
for (size_t i = 0; i < dynsurf_num; ++i) {
_G(dynamicallyCreatedSurfaces)[i] = r_data.DynamicSurfaces[i];
}
@@ -463,13 +463,13 @@ 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(),
- Math::Min((size_t)_G(gameinst)->globaldatasize, r_data.GlobalScript.Len));
+ 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(),
- Math::Min((size_t)_GP(moduleInst)[i]->globaldatasize, r_data.ScriptModules[i].Len));
+ MIN((size_t)_GP(moduleInst)[i]->globaldatasize, r_data.ScriptModules[i].Len));
}
setup_player_character(_GP(game).playercharacter);
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.cpp b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
index 30bff013b8f..9a4edea27dd 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.cpp
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
@@ -199,9 +199,9 @@ void ScummVMRendererGraphicsDriver::SetGamma(int newGamma) {
uint16 gamma_blue[256];
for (int i = 0; i < 256; i++) {
- gamma_red[i] = std::min(((int)_defaultGammaRed[i] * newGamma) / 100, 0xffff);
- gamma_green[i] = std::min(((int)_defaultGammaGreen[i] * newGamma) / 100, 0xffff);
- gamma_blue[i] = std::min(((int)_defaultGammaBlue[i] * newGamma) / 100, 0xffff);
+ gamma_red[i] = MIN(((int)_defaultGammaRed[i] * newGamma) / 100, 0xffff);
+ gamma_green[i] = MIN(((int)_defaultGammaGreen[i] * newGamma) / 100, 0xffff);
+ gamma_blue[i] = MIN(((int)_defaultGammaBlue[i] * newGamma) / 100, 0xffff);
}
SDL_SetWindowGammaRamp(sys_get_window(), gamma_red, gamma_green, gamma_blue);
diff --git a/engines/ags/engine/main/engine_setup.cpp b/engines/ags/engine/main/engine_setup.cpp
index eb65db27329..d458f98e96b 100644
--- a/engines/ags/engine/main/engine_setup.cpp
+++ b/engines/ags/engine/main/engine_setup.cpp
@@ -228,7 +228,7 @@ void engine_post_gfxmode_mouse_setup(const Size &init_desktop) {
if (_GP(usetup).mouse_speed_def == kMouseSpeed_CurrentDisplay) {
Size cur_desktop;
if (sys_get_desktop_resolution(cur_desktop.Width, cur_desktop.Height) == 0)
- _GP(mouse).SetSpeedUnit(Math::Max((float)cur_desktop.Width / (float)init_desktop.Width,
+ _GP(mouse).SetSpeedUnit(MAX((float)cur_desktop.Width / (float)init_desktop.Width,
(float)cur_desktop.Height / (float)init_desktop.Height));
}
diff --git a/engines/ags/engine/main/graphics_mode.cpp b/engines/ags/engine/main/graphics_mode.cpp
index 31d636f97d0..98adb998923 100644
--- a/engines/ags/engine/main/graphics_mode.cpp
+++ b/engines/ags/engine/main/graphics_mode.cpp
@@ -169,8 +169,8 @@ Size get_game_frame_from_screen_size(const Size &game_size, const Size screen_si
if (scale > 0)
fp_scale = convert_scaling_to_fp(scale);
else
- fp_scale = Math::Max<int32_t>(kUnit,
- Math::Min((screen_size.Width / game_size.Width) << kShift,
+ fp_scale = MAX<int32_t>(kUnit,
+ MIN((screen_size.Width / game_size.Width) << kShift,
(screen_size.Height / game_size.Height) << kShift));
Size frame_size = Size(
(game_size.Width * fp_scale) >> kShift,
@@ -222,8 +222,8 @@ bool try_init_compatible_mode(const DisplayMode &dm) {
// Windowed mode
if (dm.IsWindowed()) {
// If windowed mode, make the resolution stay in the generally supported limits
- dm_compat.Width = Math::Min(dm_compat.Width, device_size.Width);
- dm_compat.Height = Math::Min(dm_compat.Height, device_size.Height);
+ dm_compat.Width = MIN(dm_compat.Width, device_size.Width);
+ dm_compat.Height = MIN(dm_compat.Height, device_size.Height);
}
// Fullscreen mode
else {
diff --git a/engines/ags/engine/platform/base/ags_platform_driver.cpp b/engines/ags/engine/platform/base/ags_platform_driver.cpp
index 52fbf2312a2..7fc4158252a 100644
--- a/engines/ags/engine/platform/base/ags_platform_driver.cpp
+++ b/engines/ags/engine/platform/base/ags_platform_driver.cpp
@@ -258,7 +258,7 @@ void AGSPlatformDriver::Delay(int millis) {
break;
}
- auto duration = std::min<std::chrono::milliseconds>(delayUntil - now,
+ auto duration = MIN<std::chrono::milliseconds>(delayUntil - now,
_G(MaximumDelayBetweenPolling));
std::this_thread::sleep_for(duration);
now = AGS_Clock::now(); // update now
diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index 3a0217bca5e..ac564320227 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -335,7 +335,7 @@ int ccInstance::CallScriptFunction(const char *funcname, int32_t numargs, const
// Prepare instance for run
flags &= ~INSTF_ABORTED;
// Allow to pass less parameters if script callback has less declared args
- numargs = std::min(numargs, export_args);
+ numargs = MIN(numargs, export_args);
// object pointer needs to start zeroed
registers[SREG_OP].SetDynamicObject(nullptr, nullptr);
registers[SREG_SP].SetStackPtr(&stack[0]);
diff --git a/engines/ags/engine/script/script_api.cpp b/engines/ags/engine/script/script_api.cpp
index 5943b5f351e..b5ba77d715d 100644
--- a/engines/ags/engine/script/script_api.cpp
+++ b/engines/ags/engine/script/script_api.cpp
@@ -223,7 +223,7 @@ const char *ScriptSprintf(char *buffer, size_t buf_length, const char *format,
arg_idx++;
if (snprintf_res >= 0) {
// snprintf returns maximal number of characters, so limit it with buffer size
- out_ptr += Math::Min<ptrdiff_t>(snprintf_res, avail_outbuf);
+ out_ptr += MIN<ptrdiff_t>(snprintf_res, avail_outbuf);
continue;
}
// -- pass further to invalid format case
@@ -231,7 +231,7 @@ const char *ScriptSprintf(char *buffer, size_t buf_length, const char *format,
// If format was not valid, or there are no available
// parameters, just copy stored format buffer as it is
- size_t copy_len = Math::Min(Math::Min<ptrdiff_t>(fmt_bufptr - fmtbuf, fmtbuf_size - 1), avail_outbuf);
+ size_t copy_len = MIN(MIN<ptrdiff_t>(fmt_bufptr - fmtbuf, fmtbuf_size - 1), avail_outbuf);
memcpy(out_ptr, fmtbuf, copy_len);
out_ptr += copy_len;
}
diff --git a/engines/ags/shared/ac/game_setup_struct.cpp b/engines/ags/shared/ac/game_setup_struct.cpp
index a34414c47f5..ad490677641 100644
--- a/engines/ags/shared/ac/game_setup_struct.cpp
+++ b/engines/ags/shared/ac/game_setup_struct.cpp
@@ -122,7 +122,7 @@ void GameSetupStruct::read_font_infos(Shared::Stream *in, GameDataVersion data_v
for (int i = 0; i < numfonts; ++i) {
fonts[i].YOffset = in->ReadInt32();
if (data_ver >= kGameVersion_341_2)
- fonts[i].LineSpacing = Math::Max<int32_t>(0, in->ReadInt32());
+ fonts[i].LineSpacing = MAX<int32_t>(0, in->ReadInt32());
}
} else {
for (int i = 0; i < numfonts; ++i) {
@@ -130,7 +130,7 @@ void GameSetupStruct::read_font_infos(Shared::Stream *in, GameDataVersion data_v
fonts[i].Size = in->ReadInt32();
fonts[i].Outline = in->ReadInt32();
fonts[i].YOffset = in->ReadInt32();
- fonts[i].LineSpacing = Math::Max<int32_t>(0, in->ReadInt32());
+ fonts[i].LineSpacing = MAX<int32_t>(0, in->ReadInt32());
AdjustFontInfoUsingFlags(fonts[i], flags);
}
}
diff --git a/engines/ags/shared/ac/sprite_file.cpp b/engines/ags/shared/ac/sprite_file.cpp
index 1f59d494148..63160effa38 100644
--- a/engines/ags/shared/ac/sprite_file.cpp
+++ b/engines/ags/shared/ac/sprite_file.cpp
@@ -325,7 +325,7 @@ static inline void ReadSprHeader(SpriteDatHeader &hdr, Stream *in,
HError SpriteFile::RebuildSpriteIndex(Stream *in, sprkey_t topmost,
std::vector<Size> &metrics) {
- topmost = std::min(topmost, (sprkey_t)_spriteData.size() - 1);
+ topmost = MIN(topmost, (sprkey_t)_spriteData.size() - 1);
for (sprkey_t i = 0; !in->EOS() && (i <= topmost); ++i) {
_spriteData[i].Offset = in->GetPosition();
SpriteDatHeader hdr;
diff --git a/engines/ags/shared/ac/words_dictionary.cpp b/engines/ags/shared/ac/words_dictionary.cpp
index 3bc5697c82e..3019bd096d9 100644
--- a/engines/ags/shared/ac/words_dictionary.cpp
+++ b/engines/ags/shared/ac/words_dictionary.cpp
@@ -110,7 +110,7 @@ void decrypt_text(char *toenc, size_t buf_sz) {
void read_string_decrypt(Stream *in, char *buf, size_t buf_sz) {
size_t len = in->ReadInt32();
- size_t slen = std::min(buf_sz - 1, len);
+ size_t slen = MIN(buf_sz - 1, len);
in->Read(buf, slen);
if (len > slen)
in->Seek(len - slen);
diff --git a/engines/ags/shared/font/fonts.cpp b/engines/ags/shared/font/fonts.cpp
index e4cf1fce898..de90e545718 100644
--- a/engines/ags/shared/font/fonts.cpp
+++ b/engines/ags/shared/font/fonts.cpp
@@ -164,7 +164,7 @@ int get_text_width_outlined(const char *text, size_t font_number) {
return self_width + 2 * _GP(fonts)[font_number].Info.AutoOutlineThickness;
}
int outline_width = _GP(fonts)[outline].Renderer->GetTextWidth(text, outline);
- return std::max(self_width, outline_width);
+ return MAX(self_width, outline_width);
}
int get_font_outline(size_t font_number) {
@@ -209,7 +209,7 @@ int get_font_height_outlined(size_t fontNumber) {
return self_height + 2 * _GP(fonts)[fontNumber].Info.AutoOutlineThickness;
}
int outline_height = _GP(fonts)[outline].Metrics.CompatHeight;
- return std::max(self_height, outline_height);
+ return MAX(self_height, outline_height);
}
int get_font_surface_height(size_t fontNumber) {
@@ -449,8 +449,8 @@ void alloc_font_outline_buffers(size_t font_number,
(f.TextStencil.GetWidth() < text_width) || (f.TextStencil.GetHeight() < text_height)) {
int sw = f.TextStencil.IsNull() ? 0 : f.TextStencil.GetWidth();
int sh = f.TextStencil.IsNull() ? 0 : f.TextStencil.GetHeight();
- sw = std::max(text_width, sw);
- sh = std::max(text_height, sh);
+ sw = MAX(text_width, sw);
+ sh = MAX(text_height, sh);
f.TextStencil.Create(sw, sh, color_depth);
f.OutlineStencil.Create(sw, sh + thick, color_depth);
f.TextStencilSub.CreateSubBitmap(&f.TextStencil, RectWH(Size(text_width, text_height)));
diff --git a/engines/ags/shared/game/interactions.cpp b/engines/ags/shared/game/interactions.cpp
index c4307e94567..237c9b44472 100644
--- a/engines/ags/shared/game/interactions.cpp
+++ b/engines/ags/shared/game/interactions.cpp
@@ -227,7 +227,7 @@ Interaction &Interaction::operator =(const Interaction &ni) {
void Interaction::CopyTimesRun(const Interaction &inter) {
assert(Events.size() == inter.Events.size());
- size_t count = Math::Min(Events.size(), inter.Events.size());
+ size_t count = MIN(Events.size(), inter.Events.size());
for (size_t i = 0; i < count; ++i) {
Events[i].TimesRun = inter.Events[i].TimesRun;
}
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index 7c4932c4970..77e11319957 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -356,7 +356,7 @@ void ReadDialogs(DialogTopic *&dialog,
break;
}
- newlen = Math::Min(newlen, sizeof(buffer) - 1);
+ newlen = MIN(newlen, sizeof(buffer) - 1);
in->Read(buffer, newlen);
decrypt_text(buffer, newlen);
buffer[newlen] = 0;
diff --git a/engines/ags/shared/gui/gui_label.cpp b/engines/ags/shared/gui/gui_label.cpp
index da049f7b58d..02fc4801bf9 100644
--- a/engines/ags/shared/gui/gui_label.cpp
+++ b/engines/ags/shared/gui/gui_label.cpp
@@ -77,7 +77,7 @@ Rect GUILabel::CalcGraphicRect(bool clipped) {
++i, at_y += linespacing) {
Line lpos = GUI::CalcTextPositionHor(_GP(Lines)[i].GetCStr(), Font, 0, 0 + Width - 1, at_y,
(FrameAlignment)TextAlignment);
- max_line.X2 = std::max(max_line.X2, lpos.X2);
+ max_line.X2 = MAX(max_line.X2, lpos.X2);
}
return SumRects(rc, RectWH(0, 0, max_line.X2 - max_line.X1 + 1, at_y - linespacing + get_font_surface_height(Font)));
}
diff --git a/engines/ags/shared/gui/gui_listbox.cpp b/engines/ags/shared/gui/gui_listbox.cpp
index 3785b717a84..783afe5bb57 100644
--- a/engines/ags/shared/gui/gui_listbox.cpp
+++ b/engines/ags/shared/gui/gui_listbox.cpp
@@ -104,7 +104,7 @@ Rect GUIListBox::CalcGraphicRect(bool clipped) {
PrepareTextToDraw(Items[item_index]);
Line lpos = GUI::CalcTextPositionHor(_textToDraw.GetCStr(), Font, 1 + pixel_size, right_hand_edge, at_y + 1,
(FrameAlignment)TextAlignment);
- max_line.X2 = std::max(max_line.X2, lpos.X2);
+ max_line.X2 = MAX(max_line.X2, lpos.X2);
}
return SumRects(rc, RectWH(0, 0, max_line.X2 - max_line.X1 + 1, Height));
}
diff --git a/engines/ags/shared/gui/gui_slider.cpp b/engines/ags/shared/gui/gui_slider.cpp
index 1fcf6b491b1..4efe00e743c 100644
--- a/engines/ags/shared/gui/gui_slider.cpp
+++ b/engines/ags/shared/gui/gui_slider.cpp
@@ -69,10 +69,10 @@ Rect GUISlider::CalcGraphicRect(bool clipped) {
Rect bar = _cachedBar;
Rect handle = _cachedHandle;
return Rect(
- std::min(std::min(logical.Left, bar.Left), handle.Left),
- std::min(std::min(logical.Top, bar.Top), handle.Top),
- std::max(std::max(logical.Right, bar.Right), handle.Right),
- std::max(std::max(logical.Bottom, bar.Bottom), handle.Bottom)
+ MIN(MIN(logical.Left, bar.Left), handle.Left),
+ MIN(MIN(logical.Top, bar.Top), handle.Top),
+ MAX(MAX(logical.Right, bar.Right), handle.Right),
+ MAX(MAX(logical.Bottom, bar.Bottom), handle.Bottom)
);
}
@@ -136,7 +136,7 @@ void GUISlider::UpdateMetrics() {
_cachedBar = bar;
_cachedHandle = handle;
- _handleRange = std::max(1, handle_range);
+ _handleRange = MAX(1, handle_range);
}
void GUISlider::Draw(Bitmap *ds, int x, int y) {
diff --git a/engines/ags/shared/util/aligned_stream.cpp b/engines/ags/shared/util/aligned_stream.cpp
index 2fb7ef25494..873aba9d149 100644
--- a/engines/ags/shared/util/aligned_stream.cpp
+++ b/engines/ags/shared/util/aligned_stream.cpp
@@ -210,7 +210,7 @@ void AlignedStream::ReadPadding(size_t next_type) {
_block += next_type - pad;
}
- _maxAlignment = Math::Max(_maxAlignment, next_type);
+ _maxAlignment = MAX(_maxAlignment, next_type);
// Data is evenly aligned now
if (_block % LargestPossibleType == 0) {
_block = 0;
@@ -233,7 +233,7 @@ void AlignedStream::WritePadding(size_t next_type) {
_block += next_type - pad;
}
- _maxAlignment = Math::Max(_maxAlignment, next_type);
+ _maxAlignment = MAX(_maxAlignment, next_type);
// Data is evenly aligned now
if (_block % LargestPossibleType == 0) {
_block = 0;
diff --git a/engines/ags/shared/util/buffered_stream.cpp b/engines/ags/shared/util/buffered_stream.cpp
index 9470fc7ce80..a3d65a6bc11 100644
--- a/engines/ags/shared/util/buffered_stream.cpp
+++ b/engines/ags/shared/util/buffered_stream.cpp
@@ -85,7 +85,7 @@ size_t BufferedStream::Read(void *toBuffer, size_t toSize) {
soff_t bufferOffset = _position - _bufferPosition;
assert(bufferOffset >= 0);
size_t bytesLeft = _buffer.size() - (size_t)bufferOffset;
- size_t chunkSize = std::min<size_t>(bytesLeft, toSize);
+ size_t chunkSize = MIN<size_t>(bytesLeft, toSize);
memcpy(to, _buffer.data() + bufferOffset, chunkSize);
@@ -133,7 +133,7 @@ bool BufferedStream::Seek(soff_t offset, StreamSeek origin) {
}
// clamp
- _position = std::min(std::max(want_pos, (soff_t)_start), _end);
+ _position = MIN(MAX(want_pos, (soff_t)_start), _end);
return _position == want_pos;
}
@@ -141,9 +141,9 @@ BufferedSectionStream::BufferedSectionStream(const String &file_name, soff_t sta
FileOpenMode open_mode, FileWorkMode work_mode, DataEndianess stream_endianess)
: BufferedStream(file_name, open_mode, work_mode, stream_endianess) {
assert(start_pos <= end_pos);
- start_pos = std::min(start_pos, end_pos);
- _start = std::min(start_pos, _end);
- _end = std::min(end_pos, _end);
+ start_pos = MIN(start_pos, end_pos);
+ _start = MIN(start_pos, _end);
+ _end = MIN(end_pos, _end);
Seek(0, kSeekBegin);
}
diff --git a/engines/ags/shared/util/geometry.cpp b/engines/ags/shared/util/geometry.cpp
index b0a88abee58..1b1b78530ce 100644
--- a/engines/ags/shared/util/geometry.cpp
+++ b/engines/ags/shared/util/geometry.cpp
@@ -38,13 +38,13 @@ bool IsRectInsideRect(const Rect &place, const Rect &item) {
float DistanceBetween(const Rect &r1, const Rect &r2) {
// https://gamedev.stackexchange.com/a/154040
Rect rect_outer(
- std::min(r1.Left, r2.Left),
- std::min(r1.Top, r2.Top),
- std::max(r1.Right, r2.Right),
- std::max(r1.Bottom, r2.Bottom)
+ MIN(r1.Left, r2.Left),
+ MIN(r1.Top, r2.Top),
+ MAX(r1.Right, r2.Right),
+ MAX(r1.Bottom, r2.Bottom)
);
- int inner_width = std::max(0, rect_outer.GetWidth() - r1.GetWidth() - r2.GetWidth());
- int inner_height = std::max(0, rect_outer.GetHeight() - r1.GetHeight() - r2.GetHeight());
+ int inner_width = MAX(0, rect_outer.GetWidth() - r1.GetWidth() - r2.GetWidth());
+ int inner_height = MAX(0, rect_outer.GetHeight() - r1.GetHeight() - r2.GetHeight());
return static_cast<float>(std::sqrt((inner_width ^ 2) + (inner_height ^ 2)));
}
@@ -121,13 +121,13 @@ Rect PlaceInRect(const Rect &place, const Rect &item, const RectPlacement &place
}
Rect SumRects(const Rect &r1, const Rect &r2) { // NOTE: remember that in AGS Y axis is pointed downwards (top < bottom)
- return Rect(std::min(r1.Left, r2.Left), std::min(r1.Top, r2.Top),
- std::max(r1.Right, r2.Right), std::max(r1.Bottom, r2.Bottom));
+ return Rect(MIN(r1.Left, r2.Left), MIN(r1.Top, r2.Top),
+ MAX(r1.Right, r2.Right), MAX(r1.Bottom, r2.Bottom));
}
Rect IntersectRects(const Rect &r1, const Rect &r2) { // NOTE: the result may be empty (negative) rect if there's no intersection
- return Rect(std::max(r1.Left, r2.Left), std::max(r1.Top, r2.Top),
- std::min(r1.Right, r2.Right), std::min(r1.Bottom, r2.Bottom));
+ return Rect(MAX(r1.Left, r2.Left), MAX(r1.Top, r2.Top),
+ MIN(r1.Right, r2.Right), MIN(r1.Bottom, r2.Bottom));
}
} // namespace AGS3
diff --git a/engines/ags/shared/util/memory.h b/engines/ags/shared/util/memory.h
index e36842fda92..6ce13f32c44 100644
--- a/engines/ags/shared/util/memory.h
+++ b/engines/ags/shared/util/memory.h
@@ -222,7 +222,7 @@ inline void BlockCopy(uint8_t *dst, const size_t dst_pitch, const size_t dst_off
const uint8_t *src, const size_t src_pitch, const size_t src_offset,
const size_t height) {
for (size_t y = 0; y < height; ++y, src += src_pitch, dst += dst_pitch)
- memcpy(dst + dst_offset, src + src_offset, Math::Min(dst_pitch - dst_offset, src_pitch - src_offset));
+ memcpy(dst + dst_offset, src + src_offset, MIN(dst_pitch - dst_offset, src_pitch - src_offset));
}
} // namespace Memory
diff --git a/engines/ags/shared/util/memory_stream.cpp b/engines/ags/shared/util/memory_stream.cpp
index 7ac04914bc6..69bcd01f1bd 100644
--- a/engines/ags/shared/util/memory_stream.cpp
+++ b/engines/ags/shared/util/memory_stream.cpp
@@ -92,7 +92,7 @@ size_t MemoryStream::Read(void *buffer, size_t size) {
}
assert(_len > _pos);
size_t remain = _len - _pos;
- size_t read_sz = std::min(remain, size);
+ size_t read_sz = MIN(remain, size);
memcpy(buffer, _cbuf + _pos, read_sz);
_pos += read_sz;
return read_sz;
@@ -117,8 +117,8 @@ bool MemoryStream::Seek(soff_t offset, StreamSeek origin) {
default:
return false;
}
- _pos = static_cast<size_t>(std::max<soff_t>(0, pos));
- _pos = static_cast<size_t>(std::min<soff_t>(_len, pos)); // clamp to EOS
+ _pos = static_cast<size_t>(MAX<soff_t>(0, pos));
+ _pos = static_cast<size_t>(MIN<soff_t>(_len, pos)); // clamp to EOS
return true;
}
@@ -126,7 +126,7 @@ size_t MemoryStream::Write(const void *buffer, size_t size) {
if (_pos >= _buf_sz) {
return 0;
}
- size = std::min(size, _buf_sz - _pos);
+ size = MIN(size, _buf_sz - _pos);
memcpy(_buf + _pos, buffer, size);
_pos += size;
_len += size;
diff --git a/engines/ags/shared/util/string.cpp b/engines/ags/shared/util/string.cpp
index e4f8ce64188..d3387806ed8 100644
--- a/engines/ags/shared/util/string.cpp
+++ b/engines/ags/shared/util/string.cpp
@@ -144,7 +144,7 @@ void String::Write(Stream *out) const {
void String::WriteCount(Stream *out, size_t count) const {
if (out) {
- size_t str_out_len = Math::Min(count - 1, _len);
+ size_t str_out_len = MIN(count - 1, _len);
if (str_out_len > 0)
out->Write(_cstr, str_out_len);
size_t null_out_len = count - str_out_len;
@@ -173,27 +173,27 @@ int String::CompareLeftNoCase(const char *cstr, size_t count) const {
int String::CompareMid(const char *cstr, size_t from, size_t count) const {
cstr = cstr ? cstr : "";
- from = Math::Min(from, _len);
+ from = MIN(from, _len);
return strncmp(_cstr + from, cstr, count != NoIndex ? count : strlen(cstr));
}
int String::CompareMidNoCase(const char *cstr, size_t from, size_t count) const {
cstr = cstr ? cstr : "";
- from = Math::Min(from, _len);
+ from = MIN(from, _len);
return ags_strnicmp(_cstr + from, cstr, count != NoIndex ? count : strlen(cstr));
}
int String::CompareRight(const char *cstr, size_t count) const {
cstr = cstr ? cstr : "";
count = count != NoIndex ? count : strlen(cstr);
- size_t off = Math::Min(_len, count);
+ size_t off = MIN(_len, count);
return strncmp(_cstr + _len - off, cstr, count);
}
int String::CompareRightNoCase(const char *cstr, size_t count) const {
cstr = cstr ? cstr : "";
count = count != NoIndex ? count : strlen(cstr);
- size_t off = Math::Min(_len, count);
+ size_t off = MIN(_len, count);
return ags_strnicmp(_cstr + _len - off, cstr, count);
}
@@ -210,7 +210,7 @@ size_t String::FindCharReverse(char c, size_t from) const {
return NoIndex;
}
- from = Math::Min(from, _len - 1);
+ from = MIN(from, _len - 1);
const char *seek_ptr = _cstr + from;
while (seek_ptr >= _cstr) {
if (*seek_ptr == c) {
@@ -327,7 +327,7 @@ String String::Upper() const {
}
String String::Left(size_t count) const {
- count = Math::Min(count, _len);
+ count = MIN(count, _len);
return count == _len ? *this : String(_cstr, count);
}
@@ -337,7 +337,7 @@ String String::Mid(size_t from, size_t count) const {
}
String String::Right(size_t count) const {
- count = Math::Min(count, _len);
+ count = MIN(count, _len);
return count == _len ? *this : String(_cstr + _len - count, count);
}
@@ -400,7 +400,7 @@ void String::Reserve(size_t max_length) {
if (max_length > _bufHead->Capacity) {
// grow by 50%
size_t grow_length = _bufHead->Capacity + (_bufHead->Capacity / 2);
- Copy(Math::Max(max_length, grow_length));
+ Copy(MAX(max_length, grow_length));
}
} else {
Create(max_length);
@@ -469,7 +469,7 @@ void String::AppendFmtv(const char *fcstr, va_list argptr) {
void String::ClipLeft(size_t count) {
if ((_len != 0) && (count > 0)) {
- count = Math::Min(count, _len);
+ count = MIN(count, _len);
BecomeUnique();
_len -= count;
_cstr += count;
@@ -478,7 +478,7 @@ void String::ClipLeft(size_t count) {
void String::ClipMid(size_t from, size_t count) {
if (from < _len) {
- count = Math::Min(count, _len - from);
+ count = MIN(count, _len - from);
if (count > 0) {
BecomeUnique();
if (!from) {
@@ -498,7 +498,7 @@ void String::ClipMid(size_t from, size_t count) {
void String::ClipRight(size_t count) {
if (_len > 0 && count > 0) {
- count = Math::Min(count, _len);
+ count = MIN(count, _len);
BecomeUnique();
_len -= count;
_cstr[_len] = 0;
@@ -745,7 +745,7 @@ void String::SetAt(size_t index, char c) {
void String::SetString(const char *cstr, size_t length) {
if (cstr) {
- length = Math::Min(length, strlen(cstr));
+ length = MIN(length, strlen(cstr));
if (length > 0) {
ReserveAndShift(false, Math::Surplus(length, _len));
memcpy(_cstr, cstr, length);
@@ -820,7 +820,7 @@ void String::TrimRight(char c) {
void String::TruncateToLeft(size_t count) {
if (_len != 0) {
- count = Math::Min(count, _len);
+ count = MIN(count, _len);
if (count < _len) {
BecomeUnique();
_len = count;
@@ -843,7 +843,7 @@ void String::TruncateToMid(size_t from, size_t count) {
void String::TruncateToRight(size_t count) {
if (_len != 0) {
- count = Math::Min(count, _len);
+ count = MIN(count, _len);
if (count < _len) {
BecomeUnique();
_cstr += _len - count;
@@ -939,7 +939,7 @@ void String::Copy(size_t max_length, size_t offset) {
char *new_data = new char[sizeof(String::BufHeader) + max_length + 1];
// remember, that _cstr may point to any address in buffer
char *cstr_head = new_data + sizeof(String::BufHeader) + offset;
- size_t copy_length = Math::Min(_len, max_length);
+ size_t copy_length = MIN(_len, max_length);
memcpy(cstr_head, _cstr, copy_length);
Free();
_buf = new_data;
@@ -974,7 +974,7 @@ void String::ReserveAndShift(bool left, size_t more_length) {
if (_bufHead->Capacity < total_length) { // not enough capacity - reallocate buffer
// grow by 50% or at least to total_size
size_t grow_length = _bufHead->Capacity + (_bufHead->Capacity >> 1);
- Copy(Math::Max(total_length, grow_length), left ? more_length : 0u);
+ Copy(MAX(total_length, grow_length), left ? more_length : 0u);
} else if (_bufHead->RefCount > 1) { // is a shared string - clone buffer
Copy(total_length, left ? more_length : 0u);
} else {
diff --git a/engines/ags/shared/util/string_utils.cpp b/engines/ags/shared/util/string_utils.cpp
index 353e2579f9e..f5bf7773922 100644
--- a/engines/ags/shared/util/string_utils.cpp
+++ b/engines/ags/shared/util/string_utils.cpp
@@ -130,7 +130,7 @@ void StrUtil::ReadString(char *cstr, Stream *in, size_t buf_limit) {
return;
}
- len = Math::Min(len, buf_limit - 1);
+ len = MIN(len, buf_limit - 1);
if (len > 0)
in->Read(cstr, len);
cstr[len] = 0;
diff --git a/engines/ags/shared/util/text_stream_reader.cpp b/engines/ags/shared/util/text_stream_reader.cpp
index 79d8f34dfe0..f4c6de4fdb0 100644
--- a/engines/ags/shared/util/text_stream_reader.cpp
+++ b/engines/ags/shared/util/text_stream_reader.cpp
@@ -85,10 +85,10 @@ String TextStreamReader::ReadLine() {
if (c < chars_read_last && *seek_ptr == '\n') {
line_break_position = seek_ptr - char_buffer;
if (str_len < max_chars) {
- append_length = Math::Min(line_break_position, max_chars - str_len);
+ append_length = MIN(line_break_position, max_chars - str_len);
}
} else {
- append_length = Math::Min(chars_read_last, max_chars - str_len);
+ append_length = MIN(chars_read_last, max_chars - str_len);
}
if (append_length > 0) {
Commit: 86c363a8dda160c0328a7907e8b2f244d0b5a535
https://github.com/scummvm/scummvm/commit/86c363a8dda160c0328a7907e8b2f244d0b5a535
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:10-07:00
Commit Message:
AGS: Remove ScriptOverlay.hasInternalRef flag, add actual ref
>From update ef0655b601004983d13dab99092d708b080eef23
Changed paths:
engines/ags/engine/ac/character.cpp
engines/ags/engine/ac/dynobj/script_overlay.cpp
engines/ags/engine/ac/dynobj/script_overlay.h
engines/ags/engine/ac/overlay.cpp
engines/ags/engine/ac/overlay.h
engines/ags/engine/ac/screen_overlay.h
diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index 7a6f6937dd1..467fe4baba2 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -706,9 +706,8 @@ ScriptOverlay *Character_SayBackground(CharacterInfo *chaa, const char *texx) {
if (ovri < 0)
quit("!SayBackground internal error: no overlay");
- ScriptOverlay *scOver = create_scriptobj_for_overlay(_GP(screenover)[ovri]);
- scOver->hasInternalRef = true; // keep at least until internal timeout
- return scOver;
+ // Create script object with an internal ref, keep at least until internal timeout
+ return create_scriptobj_for_overlay(_GP(screenover)[ovri], true);
}
void Character_SetAsPlayer(CharacterInfo *chaa) {
diff --git a/engines/ags/engine/ac/dynobj/script_overlay.cpp b/engines/ags/engine/ac/dynobj/script_overlay.cpp
index 879cb35f1ba..184cfca563a 100644
--- a/engines/ags/engine/ac/dynobj/script_overlay.cpp
+++ b/engines/ags/engine/ac/dynobj/script_overlay.cpp
@@ -43,8 +43,8 @@ int ScriptOverlay::Dispose(const char *address, bool force) {
// if this is being removed voluntarily (ie. pointer out of
// scope) then remove the associateed overlay
- // Otherwise, it's a Restre Game or something so don't
- if ((!force) && (!hasInternalRef) && (Overlay_GetValid(this))) {
+ // Otherwise, it's a Restore Game or something so don't
+ if ((!force) && (Overlay_GetValid(this))) {
Remove();
}
@@ -64,14 +64,14 @@ void ScriptOverlay::Serialize(const char *address, Stream *out) {
out->WriteInt32(overlayId);
out->WriteInt32(0); // unused (was text window x padding)
out->WriteInt32(0); // unused (was text window y padding)
- out->WriteInt32(hasInternalRef);
+ out->WriteInt32(0); // unused (was internal ref flag)
}
void ScriptOverlay::Unserialize(int index, Stream *in, size_t data_sz) {
overlayId = in->ReadInt32();
in->ReadInt32(); // unused (was text window x padding)
in->ReadInt32(); // unused (was text window y padding)
- hasInternalRef = in->ReadInt32() != 0;
+ in->ReadInt32(); // unused (was internal ref flag)
ccRegisterUnserializedObject(index, this, this);
}
diff --git a/engines/ags/engine/ac/dynobj/script_overlay.h b/engines/ags/engine/ac/dynobj/script_overlay.h
index b9af4f29cb6..5b29b3ccdea 100644
--- a/engines/ags/engine/ac/dynobj/script_overlay.h
+++ b/engines/ags/engine/ac/dynobj/script_overlay.h
@@ -28,9 +28,6 @@ namespace AGS3 {
struct ScriptOverlay final : AGSCCDynamicObject {
int overlayId = -1;
- // TODO: this flag is needed to mark an overlay which lifetime is managed
- // by the engine; this may be solved with engine owning an object ref instead
- bool hasInternalRef = false;
int Dispose(const char *address, bool force) override;
const char *GetType() override;
diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index afeb63445fb..442acf0ab33 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -222,19 +222,14 @@ void Overlay_SetZOrder(ScriptOverlay *scover, int zorder) {
//=============================================================================
// Creates and registers a managed script object for existing overlay object
-ScriptOverlay *create_scriptobj_for_overlay(ScreenOverlay &over) {
+// optionally adds an internal engine reference to prevent object's disposal
+ScriptOverlay *create_scriptobj_for_overlay(ScreenOverlay &over, bool internal_ref) {
ScriptOverlay *scover = new ScriptOverlay();
scover->overlayId = over.type;
int handl = ccRegisterManagedObject(scover, scover);
over.associatedOverlayHandle = handl;
- return scover;
-}
-
-// Creates managed script object for overlay and adds internal engine's reference to it,
-// so that it does not get disposed even if there are no user references in script.
-static ScriptOverlay *create_scriptobj_addref(ScreenOverlay &over) {
- ScriptOverlay *scover = create_scriptobj_for_overlay(over);
- ccAddObjectReference(over.associatedOverlayHandle);
+ if (internal_ref)
+ ccAddObjectReference(handl);
return scover;
}
@@ -270,7 +265,10 @@ void remove_screen_overlay_index(size_t over_idx) {
if (_GP(play).speech_face_scover)
invalidate_and_subref(over, _GP(play).speech_face_scover);
_G(face_talking) = -1;
+ } else if (over.bgSpeechForChar > 0) { // release internal ref for bg speech
+ ccReleaseObjectReference(over.associatedOverlayHandle);
}
+
dispose_overlay(over);
_GP(screenover).erase(_GP(screenover).begin() + over_idx);
// if an overlay before the sierra-style speech one is removed, update the index
@@ -334,9 +332,9 @@ size_t add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, int pic
// only make script object for blocking speech now, because messagebox blocks all script
// and therefore cannot be accessed, so no practical reason for that atm
if (type == OVER_TEXTSPEECH)
- _GP(play).speech_text_scover = create_scriptobj_addref(over);
+ _GP(play).speech_text_scover = create_scriptobj_for_overlay(over, true);
} else if (type == OVER_PICTURE) {
- _GP(play).speech_face_scover = create_scriptobj_addref(over);
+ _GP(play).speech_face_scover = create_scriptobj_for_overlay(over, true);
}
over.MarkChanged();
diff --git a/engines/ags/engine/ac/overlay.h b/engines/ags/engine/ac/overlay.h
index 40c640eab09..ee10201c249 100644
--- a/engines/ags/engine/ac/overlay.h
+++ b/engines/ags/engine/ac/overlay.h
@@ -53,8 +53,9 @@ Point get_overlay_position(const ScreenOverlay &over);
size_t add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, bool alphaChannel = false);
size_t add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, int pic_offx, int pic_offy, bool alphaChannel = false);
void remove_screen_overlay_index(size_t over_idx);
-// Creates and registers a managed script object for existing overlay object
-ScriptOverlay *create_scriptobj_for_overlay(ScreenOverlay &over);
+// Creates and registers a managed script object for existing overlay object;
+// optionally adds an internal engine reference to prevent object's disposal
+ScriptOverlay *create_scriptobj_for_overlay(ScreenOverlay &over, bool internal_ref = false);
void recreate_overlay_ddbs();
} // namespace AGS3
diff --git a/engines/ags/engine/ac/screen_overlay.h b/engines/ags/engine/ac/screen_overlay.h
index 19214bcbe72..52e031832bd 100644
--- a/engines/ags/engine/ac/screen_overlay.h
+++ b/engines/ags/engine/ac/screen_overlay.h
@@ -65,7 +65,7 @@ struct ScreenOverlay {
// Width and height to stretch the texture to
int scaleWidth = 0, scaleHeight = 0;
int bgSpeechForChar = -1;
- int associatedOverlayHandle = 0;
+ int associatedOverlayHandle = 0; // script obj handle
int zorder = INT_MIN;
bool positionRelativeToScreen = false;
bool hasSerializedBitmap = false;
Commit: ec38c1c61cfa5b7dfc4a75ebcfa7689a9a2a5263
https://github.com/scummvm/scummvm/commit/ec38c1c61cfa5b7dfc4a75ebcfa7689a9a2a5263
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:10-07:00
Commit Message:
AGS: Refactor core overlay creation funcs to return ScreenOverlay*
>From upstream f89b2e8e59da107fcbb7a75bf7e1aa293a45fb2b
Changed paths:
engines/ags/engine/ac/display.cpp
engines/ags/engine/ac/display.h
engines/ags/engine/ac/global_overlay.cpp
engines/ags/engine/ac/global_overlay.h
engines/ags/engine/ac/overlay.cpp
engines/ags/engine/ac/overlay.h
engines/ags/shared/ac/sprite_cache.h
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index 43365732cf6..308a955701d 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -70,7 +70,7 @@ struct DisplayVars {
// Pass yy = -1 to find Y co-ord automatically
// allowShrink = 0 for none, 1 for leftwards, 2 for rightwards
// pass blocking=2 to create permanent overlay
-int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int usingfont, int asspch, int isThought, int allowShrink, bool overlayPositionFixed) {
+ScreenOverlay *_display_main(int xx, int yy, int wii, const char *text, int disp_type, int usingfont, int asspch, int isThought, int allowShrink, bool overlayPositionFixed) {
const bool use_speech_textwindow = (asspch < 0) && (_GP(game).options[OPT_SPEECHTYPE] >= 2);
const bool use_thought_gui = (isThought) && (_GP(game).options[OPT_THOUGHTGUI] > 0);
@@ -252,11 +252,11 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
default: ovrtype = disp_type; break; // must be precreated overlay id
}
- int nse = add_screen_overlay(xx, yy, ovrtype, text_window_ds, adjustedXX - xx, adjustedYY - yy, alphaChannel);
+ size_t nse = add_screen_overlay(xx, yy, ovrtype, text_window_ds, adjustedXX - xx, adjustedYY - yy, alphaChannel);
// we should not delete text_window_ds here, because it is now owned by Overlay
if (disp_type >= DISPLAYTEXT_NORMALOVERLAY) {
- return _GP(screenover)[nse].type;
+ return &_GP(screenover)[nse];
}
//
@@ -268,7 +268,7 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
remove_screen_overlay(OVER_TEXTMSG);
_GP(play).SetWaitSkipResult(SKIP_AUTOTIMER);
_GP(play).messagetime = -1;
- return 0;
+ return nullptr;
}
int countdown = GetTextDisplayTime(todis);
@@ -351,7 +351,7 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
}
_GP(play).messagetime = -1;
- return 0;
+ return nullptr;
}
void _display_at(int xx, int yy, int wii, const char *text, int disp_type, int asspch, int isThought, int allowShrink, bool overlayPositionFixed) {
diff --git a/engines/ags/engine/ac/display.h b/engines/ags/engine/ac/display.h
index 1a30cda060d..7047868c142 100644
--- a/engines/ags/engine/ac/display.h
+++ b/engines/ags/engine/ac/display.h
@@ -37,7 +37,12 @@ using AGS::Shared::GUIMain;
#define DISPLAYTEXT_NORMALOVERLAY 2
// also accepts explicit overlay ID >= OVER_CUSTOM
-int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int usingfont, int asspch, int isThought, int allowShrink, bool overlayPositionFixed);
+struct ScreenOverlay;
+// Creates a textual overlay using the given parameters;
+// Pass yy = -1 to find Y co-ord automatically
+// allowShrink = 0 for none, 1 for leftwards, 2 for rightwards
+// pass blocking=2 to create permanent overlay
+ScreenOverlay *_display_main(int xx, int yy, int wii, const char *text, int disp_type, int usingfont, int asspch, int isThought, int allowShrink, bool overlayPositionFixed);
void _display_at(int xx, int yy, int wii, const char *text, int disp_type, int asspch, int isThought, int allowShrink, bool overlayPositionFixed);
// Tests the given string for the voice-over tags and plays cue clip for the given character;
// will assign replacement string, which will be blank string if game is in "voice-only" mode
diff --git a/engines/ags/engine/ac/global_overlay.cpp b/engines/ags/engine/ac/global_overlay.cpp
index c2c26a2cbbf..0b540623b34 100644
--- a/engines/ags/engine/ac/global_overlay.cpp
+++ b/engines/ags/engine/ac/global_overlay.cpp
@@ -21,19 +21,10 @@
#include "ags/engine/ac/global_overlay.h"
#include "ags/shared/ac/common.h"
-#include "ags/engine/ac/display.h"
#include "ags/engine/ac/draw.h"
-#include "ags/shared/ac/game_setup_struct.h"
-#include "ags/engine/ac/game_state.h"
-#include "ags/engine/ac/global_translation.h"
#include "ags/engine/ac/overlay.h"
#include "ags/engine/ac/runtime_defines.h"
-#include "ags/engine/ac/screen_overlay.h"
-#include "ags/engine/ac/string.h"
-#include "ags/shared/ac/sprite_cache.h"
-#include "ags/engine/ac/system.h"
-#include "ags/shared/gfx/bitmap.h"
-#include "ags/shared/util/wgt2_allg.h"
+#include "ags/globals.h"
namespace AGS3 {
@@ -45,21 +36,9 @@ void RemoveOverlay(int ovrid) {
remove_screen_overlay(ovrid);
}
-int CreateGraphicOverlay(int xx, int yy, int slott, int trans) {
- data_to_game_coords(&xx, &yy);
-
- Bitmap *screeno = BitmapHelper::CreateTransparentBitmap(_GP(game).SpriteInfos[slott].Width, _GP(game).SpriteInfos[slott].Height, _GP(game).GetColorDepth());
- wputblock(screeno, 0, 0, _GP(spriteset)[slott], trans);
- bool hasAlpha = (_GP(game).SpriteInfos[slott].Flags & SPF_ALPHACHANNEL) != 0;
- int nse = add_screen_overlay(xx, yy, OVER_CUSTOM, screeno, hasAlpha);
- return _GP(screenover)[nse].type;
-}
-
-int CreateTextOverlayCore(int xx, int yy, int wii, int fontid, int text_color, const char *text, int disp_type, int allowShrink) {
- if (wii < 8) wii = _GP(play).GetUIViewport().GetWidth() / 2;
- if (xx < 0) xx = _GP(play).GetUIViewport().GetWidth() / 2 - wii / 2;
- if (text_color == 0) text_color = 16;
- return _display_main(xx, yy, wii, text, disp_type, fontid, -text_color, 0, allowShrink, false);
+int CreateGraphicOverlay(int x, int y, int slot, int trans) {
+ auto *over = Overlay_CreateGraphicCore(x, y, slot, trans != 0);
+ return over ? over->type : 0;
}
int CreateTextOverlay(int xx, int yy, int wii, int fontid, int text_color, const char *text, int disp_type) {
@@ -71,7 +50,8 @@ int CreateTextOverlay(int xx, int yy, int wii, int fontid, int text_color, const
} else // allow DisplaySpeechBackground to be shrunk
allowShrink = 1;
- return CreateTextOverlayCore(xx, yy, wii, fontid, text_color, text, disp_type, allowShrink);
+ auto *over = Overlay_CreateTextCore(xx, yy, wii, fontid, text_color, text, disp_type, allowShrink);
+ return over ? over->type : 0;
}
void SetTextOverlay(int ovrid, int xx, int yy, int wii, int fontid, int text_color, const char *text) {
diff --git a/engines/ags/engine/ac/global_overlay.h b/engines/ags/engine/ac/global_overlay.h
index f77593b9ef8..5977631e738 100644
--- a/engines/ags/engine/ac/global_overlay.h
+++ b/engines/ags/engine/ac/global_overlay.h
@@ -24,9 +24,10 @@
namespace AGS3 {
+struct ScreenOverlay;
+
void RemoveOverlay(int ovrid);
int CreateGraphicOverlay(int xx, int yy, int slott, int trans);
-int CreateTextOverlayCore(int xx, int yy, int wii, int fontid, int text_color, const char *text, int disp_type, int allowShrink);
int CreateTextOverlay(int xx, int yy, int wii, int fontid, int clr, const char *text, int disp_type);
void SetTextOverlay(int ovrid, int xx, int yy, int wii, int fontid, int text_color, const char *text);
void MoveOverlay(int ovrid, int newx, int newy);
diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index 442acf0ab33..ad6a82d51b9 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -22,6 +22,7 @@
#include "ags/lib/std/algorithm.h"
#include "ags/engine/ac/overlay.h"
#include "ags/shared/ac/common.h"
+#include "ags/shared/ac/sprite_cache.h"
#include "ags/shared/ac/view.h"
#include "ags/engine/ac/character.h"
#include "ags/engine/ac/character_extras.h"
@@ -167,20 +168,36 @@ int Overlay_GetValid(ScriptOverlay *scover) {
return 1;
}
+ScreenOverlay *Overlay_CreateGraphicCore(int x, int y, int slot, bool transparent) {
+ data_to_game_coords(&x, &y);
+ Bitmap *screeno = BitmapHelper::CreateTransparentBitmap(_GP(game).SpriteInfos[slot].Width, _GP(game).SpriteInfos[slot].Height, _GP(game).GetColorDepth());
+ screeno->Blit(_GP(spriteset)[slot], 0, 0, transparent ? kBitmap_Transparency : kBitmap_Copy);
+ size_t nse = add_screen_overlay(x, y, OVER_CUSTOM, screeno, (_GP(game).SpriteInfos[slot].Flags & SPF_ALPHACHANNEL) != 0);
+ return nse < SIZE_MAX ? &_GP(screenover)[nse] : nullptr;
+}
+
+ScreenOverlay *Overlay_CreateTextCore(int x, int y, int width, int font, int text_color,
+ const char *text, int disp_type, int allow_shrink) {
+ if (width < 8) width = _GP(play).GetUIViewport().GetWidth() / 2;
+ if (x < 0) x = _GP(play).GetUIViewport().GetWidth() / 2 - width / 2;
+ if (text_color == 0) text_color = 16;
+ return _display_main(x, y, width, text, disp_type, font, -text_color, 0, allow_shrink, false);
+}
+
ScriptOverlay *Overlay_CreateGraphical(int x, int y, int slot, int transparent) {
+ auto *over = Overlay_CreateGraphicCore(x, y, slot, transparent != 0);
ScriptOverlay *sco = new ScriptOverlay();
- sco->overlayId = CreateGraphicOverlay(x, y, slot, transparent);
+ sco->overlayId = over->type;
ccRegisterManagedObject(sco, sco);
return sco;
}
ScriptOverlay *Overlay_CreateTextual(int x, int y, int width, int font, int colour, const char *text) {
- ScriptOverlay *sco = new ScriptOverlay();
-
data_to_game_coords(&x, &y);
width = data_to_game_coord(width);
-
- sco->overlayId = CreateTextOverlayCore(x, y, width, font, colour, text, DISPLAYTEXT_NORMALOVERLAY, 0);
+ auto *over = Overlay_CreateTextCore(x, y, width, font, colour, text, DISPLAYTEXT_NORMALOVERLAY, 0);
+ ScriptOverlay *sco = new ScriptOverlay();
+ sco->overlayId = over->type;
ccRegisterManagedObject(sco, sco);
return sco;
}
diff --git a/engines/ags/engine/ac/overlay.h b/engines/ags/engine/ac/overlay.h
index ee10201c249..9d653ceed68 100644
--- a/engines/ags/engine/ac/overlay.h
+++ b/engines/ags/engine/ac/overlay.h
@@ -45,6 +45,9 @@ void Overlay_SetY(ScriptOverlay *scover, int newy);
int Overlay_GetValid(ScriptOverlay *scover);
ScriptOverlay *Overlay_CreateGraphical(int x, int y, int slot, int transparent);
ScriptOverlay *Overlay_CreateTextual(int x, int y, int width, int font, int colour, const char *text);
+ScreenOverlay *Overlay_CreateGraphicCore(int x, int y, int slot, bool transparent);
+ScreenOverlay *Overlay_CreateTextCore(int x, int y, int width, int font, int text_color,
+ const char *text, int disp_type, int allow_shrink);
int find_overlay_of_type(int type);
void remove_screen_overlay(int type);
diff --git a/engines/ags/shared/ac/sprite_cache.h b/engines/ags/shared/ac/sprite_cache.h
index 411948b2aab..93b63d83773 100644
--- a/engines/ags/shared/ac/sprite_cache.h
+++ b/engines/ags/shared/ac/sprite_cache.h
@@ -143,7 +143,7 @@ public:
void SetMaxCacheSize(size_t size);
// Loads (if it's not in cache yet) and returns bitmap by the sprite index
- Shared::Bitmap *operator[] (sprkey_t index);
+ Shared::Bitmap *operator[](sprkey_t index);
private:
void Init();
Commit: 13f40609c7e2f1fad134bbfc16d5345083c7ca61
https://github.com/scummvm/scummvm/commit/13f40609c7e2f1fad134bbfc16d5345083c7ca61
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:10-07:00
Commit Message:
AGS: Reset currentline when exiting script function, for cc_errors
>From upstream 538e9072b03b0441853ac0022d17f8990065f8de
Changed paths:
engines/ags/engine/script/cc_instance.cpp
diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index ac564320227..384a61c3065 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -354,6 +354,7 @@ int ccInstance::CallScriptFunction(const char *funcname, int32_t numargs, const
ASSERT_STACK_SIZE(numargs);
PopValuesFromStack(numargs);
pc = 0;
+ _G(currentline) = 0;
_GP(InstThreads).pop_back(); // pop instance thread
if (reterr != 0)
return reterr;
Commit: d38596820996de74746aceef369704706c27d870
https://github.com/scummvm/scummvm/commit/d38596820996de74746aceef369704706c27d870
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-05T22:41:10-07:00
Commit Message:
AGS: Tidy up mobile config once more and get rid of psp_* variables
>From upstream 4ba8fbed2f16786e86f201f57fdaaa91cc887700
Changed paths:
engines/ags/engine/ac/game_setup.cpp
engines/ags/engine/ac/game_setup.h
engines/ags/engine/main/config.cpp
engines/ags/engine/main/engine.cpp
engines/ags/engine/main/main.cpp
engines/ags/engine/platform/base/ags_platform_driver.h
engines/ags/globals.h
diff --git a/engines/ags/engine/ac/game_setup.cpp b/engines/ags/engine/ac/game_setup.cpp
index 9af8dfbdc20..b6526473bc9 100644
--- a/engines/ags/engine/ac/game_setup.cpp
+++ b/engines/ags/engine/ac/game_setup.cpp
@@ -41,6 +41,7 @@ GameSetup::GameSetup() {
RenderAtScreenRes = false;
Supersampling = 1;
clear_cache_on_room_change = false;
+ load_latest_save = false;
rotation = kScreenRotation_Unlocked;
Screen.Params.RefreshRate = 0;
diff --git a/engines/ags/engine/ac/game_setup.h b/engines/ags/engine/ac/game_setup.h
index ccef879bbad..718e0a13ab7 100644
--- a/engines/ags/engine/ac/game_setup.h
+++ b/engines/ags/engine/ac/game_setup.h
@@ -92,7 +92,8 @@ struct GameSetup {
MouseSpeedDef mouse_speed_def;
bool RenderAtScreenRes; // render sprites at screen resolution, as opposed to native one
int Supersampling;
- bool clear_cache_on_room_change; // compatibility
+ bool clear_cache_on_room_change; // for low-end devices: clear resource caches on room change
+ bool load_latest_save; // load latest saved game on launch
ScreenRotation rotation;
DisplayModeSetup Screen;
diff --git a/engines/ags/engine/main/config.cpp b/engines/ags/engine/main/config.cpp
index 9f136028fb3..2e8aa8e6bb0 100644
--- a/engines/ags/engine/main/config.cpp
+++ b/engines/ags/engine/main/config.cpp
@@ -262,68 +262,8 @@ static void read_legacy_graphics_config(const ConfigTree &cfg) {
_GP(usetup).Screen.Params.RefreshRate = CfgReadInt(cfg, "misc", "refresh");
}
-
void override_config_ext(ConfigTree &cfg) {
- // Mobile ports always run in fullscreen mode
-#if AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_IOS
- CfgWriteInt(cfg, "graphics", "windowed", 0);
-#endif
-
- // psp_gfx_renderer - rendering mode
- // * 0 - software renderer
- // * 1 - hardware, render to screen
- // * 2 - hardware, render to texture
- if (_G(psp_gfx_renderer) == 0) {
- CfgWriteString(cfg, "graphics", "driver", "Software");
- CfgWriteInt(cfg, "graphics", "render_at_screenres", 1);
- } else {
- CfgWriteString(cfg, "graphics", "driver", "OGL");
- CfgWriteInt(cfg, "graphics", "render_at_screenres", _G(psp_gfx_renderer) == 1);
- }
-
- // psp_gfx_scaling - scaling style:
- // * 0 - no scaling
- // * 1 - stretch and preserve aspect ratio
- // * 2 - stretch to whole screen
- if (_G(psp_gfx_scaling) == 0)
- CfgWriteString(cfg, "graphics", "game_scale_fs", "1");
- else if (_G(psp_gfx_scaling) == 1)
- CfgWriteString(cfg, "graphics", "game_scale_fs", "proportional");
- else
- CfgWriteString(cfg, "graphics", "game_scale_fs", "stretch");
-
- // psp_gfx_smoothing - scaling filter:
- // * 0 - nearest-neighbour
- // * 1 - linear
- if (_G(psp_gfx_smoothing) == 0)
- CfgWriteString(cfg, "graphics", "filter", "StdScale");
- else
- CfgWriteString(cfg, "graphics", "filter", "Linear");
-
- // psp_gfx_super_sampling - enable super sampling
- // * 0 - x1
- // * 1 - x2
- if (_G(psp_gfx_renderer) == 2)
- CfgWriteInt(cfg, "graphics", "supersampling", _G(psp_gfx_super_sampling) + 1);
- else
- CfgWriteInt(cfg, "graphics", "supersampling", 0);
-
- // psp_gfx_rotation - scaling style:
- // * 0 - unlocked, let the user rotate as wished.
- // * 1 - portrait
- // * 2 - landscape
- CfgWriteInt(cfg, "graphics", "rotation", _G(psp_rotation));
-
-#if AGS_PLATFORM_OS_ANDROID
- // config_mouse_control_mode - enable relative mouse mode
- // * 1 - relative mouse touch controls
- // * 0 - direct touch mouse control
- CfgWriteInt(cfg, "mouse", "control_enabled", config_mouse_control_mode);
-#endif
-
- CfgWriteInt(cfg, "misc", "antialias", _G(psp_gfx_smooth_sprites) != 0);
- CfgWriteString(cfg, "language", "translation", _G(psp_translation));
- CfgWriteInt(cfg, "misc", "clear_cache_on_room_change", _G(psp_clear_cache_on_room_change) != 0);
+ _G(platform)->ReadConfiguration(cfg);
}
void apply_config(const ConfigTree &cfg) {
@@ -373,6 +313,7 @@ void apply_config(const ConfigTree &cfg) {
_GP(usetup).no_speech_pack = !CfgReadBoolInt(cfg, "sound", "usespeech", true);
_GP(usetup).clear_cache_on_room_change = CfgReadBoolInt(cfg, "misc", "clear_cache_on_room_change", _GP(usetup).clear_cache_on_room_change);
+ _GP(usetup).load_latest_save = CfgReadBoolInt(cfg, "misc", "load_latest_save", _GP(usetup).load_latest_save);
_GP(usetup).user_data_dir = CfgReadString(cfg, "misc", "user_data_dir");
_GP(usetup).shared_data_dir = CfgReadString(cfg, "misc", "shared_data_dir");
diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index 20ea7e1420e..eebaeef632f 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -792,10 +792,13 @@ void engine_prepare_to_start_game() {
engine_setup_scsystem_auxiliary();
-#if AGS_PLATFORM_OS_ANDROID
- if (psp_load_latest_savegame)
- selectLatestSavegame();
+ if (_GP(usetup).load_latest_save) {
+#ifndef AGS_PLATFORM_SCUMMVM
+ int slot = GetLastSaveSlot();
+ if (slot >= 0)
+ loadSaveGameOnStartup = get_save_game_path(slot);
#endif
+ }
}
// TODO: move to test unit
@@ -961,11 +964,9 @@ void engine_read_config(ConfigTree &cfg) {
Path::ComparePaths(user_cfg_file, user_global_cfg_file) != 0)
IniUtil::Read(user_cfg_file, cfg);
- // Apply overriding options from mobile port settings
+ // Apply overriding options from platform settings
// TODO: normally, those should be instead stored in the same config file in a uniform way
- // NOTE: the variable is historically called "ignore" but we use it in "override" meaning here
- if (_G(psp_ignore_acsetup_cfg_file))
- override_config_ext(cfg);
+ override_config_ext(cfg);
}
// Gathers settings from all available sources into single ConfigTree
diff --git a/engines/ags/engine/main/main.cpp b/engines/ags/engine/main/main.cpp
index 19648954c68..cc71dc641cd 100644
--- a/engines/ags/engine/main/main.cpp
+++ b/engines/ags/engine/main/main.cpp
@@ -43,10 +43,6 @@
namespace AGS3 {
-#if AGS_PLATFORM_OS_WINDOWS && !AGS_PLATFORM_DEBUG
-#define USE_CUSTOM_EXCEPTION_HANDLER
-#endif
-
using namespace AGS::Shared;
using namespace AGS::Engine;
@@ -185,6 +181,7 @@ void main_print_help() {
}
int main_process_cmdline(ConfigTree &cfg, int argc, const char *argv[]) {
+ int datafile_argv = 0;
for (int ee = 1; ee < argc; ++ee) {
const char *arg = argv[ee];
//
@@ -283,11 +280,12 @@ int main_process_cmdline(ConfigTree &cfg, int argc, const char *argv[]) {
cfg["log"][logarg.Left(split_at)] = logarg.Mid(split_at + 1);
else
cfg["log"][logarg] = "";
- }
+ } else if (arg[0] != '-') datafile_argv = ee;
}
- // assign standard path (defined in their own platform implementation)
- _G(cmdGameDataPath) = _G(psp_game_file_name);
+ if (datafile_argv > 0) {
+ _G(cmdGameDataPath) = _G(platform)->GetCommandArg(datafile_argv);
+ }
if (_G(tellInfoKeys).size() > 0)
_G(justTellInfo) = true;
diff --git a/engines/ags/engine/platform/base/ags_platform_driver.h b/engines/ags/engine/platform/base/ags_platform_driver.h
index b4a087f9001..bee844e3f9a 100644
--- a/engines/ags/engine/platform/base/ags_platform_driver.h
+++ b/engines/ags/engine/platform/base/ags_platform_driver.h
@@ -86,6 +86,8 @@ struct AGSPlatformDriver
virtual void DisplayAlert(const char *, ...) = 0;
virtual void AttachToParentConsole();
virtual int GetLastSystemError();
+ // Optionally fill in config tree from the platform-specific config source
+ virtual void ReadConfiguration(Shared::ConfigTree &cfg) {}
// Get root directory for storing per-game shared data
virtual FSLocation GetAllUsersDataDirectory() {
return FSLocation(".");
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 0077f314ac8..9b88b069835 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -1086,17 +1086,8 @@ public:
std::set<String> _tellInfoKeys;
int _loadSaveGameOnStartup = -1;
-#if ! AGS_PLATFORM_DEFINES_PSP_VARS
- int _psp_video_framedrop = 1;
- int _psp_ignore_acsetup_cfg_file = 0;
- int _psp_clear_cache_on_room_change = 0; // clear --sprite cache-- when room is unloaded
-
-#if defined(AGS_PLATFORM_SCUMMVM) && AGS_PLATFORM_SCUMMVM
- int _psp_audio_cachesize = 10;
-#endif
- const char *_psp_game_file_name = "";
- const char *_psp_translation = "default";
-
+#if 0
+ //! AGS_PLATFORM_DEFINES_PSP_VARS
int _psp_rotation = 0;
int _psp_gfx_renderer = 0;
int _psp_gfx_scaling = 1;
More information about the Scummvm-git-logs
mailing list