Initial commit

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

View File

@@ -0,0 +1,40 @@
/* 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/core/platform.h"
#include "ags/tests/test_all.h"
namespace AGS3 {
void Test_DoAllTests() {
Test_Math();
Test_Memory();
// The commented out tests don't work right now (will fix, but that is not my problem right now) @eklipsed
//Test_Path();
Test_ScriptSprintf();
Test_String();
Test_Version();
//Test_File();
//Test_IniFile();
Test_Gfx();
}
} // namespace AGS3

View File

@@ -0,0 +1,47 @@
/* 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/core/platform.h"
namespace AGS3 {
extern void Test_DoAllTests();
// Math tests
extern void Test_Math();
// File tests
extern void Test_File();
extern void Test_IniFile();
// Graphics tests
extern void Test_Gfx();
// Memory / bit-byte operations
extern void Test_Memory();
// String tests
extern void Test_ScriptSprintf();
extern void Test_String();
extern void Test_Path();
extern void Test_Version();
} // namespace AGS3

View File

@@ -0,0 +1,198 @@
/* 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/core/platform.h"
//#include <string.h>
//#include "ags/shared/debugging/assert.h"
// File not present??
#include "common/scummsys.h"
#include "ags/shared/util/aligned_stream.h"
#include "ags/shared/util/file.h"
namespace AGS3 {
using namespace AGS::Shared;
struct TTrickyAlignedData {
char a;
int b;
int c;
short d[3];
int e;
char f[17];
int g[4];
short h[13];
char i[3];
short j;
int k;
short l;
short m;
int n;
int64_t i64a;
char o;
int64_t i64b;
short p;
int64_t i64c;
short q;
short r;
int64_t i64d;
char final;
};
void Test_File() {
//-----------------------------------------------------
// Operations
Stream *out = File::OpenFile("test.tmp", AGS::Shared::kFile_CreateAlways, AGS::Shared::kFile_Write);
out->WriteInt16(10);
out->WriteInt64(-20202);
//String::WriteString("test.tmp", out);
String("test.tmp").Write(out);
String very_long_string;
very_long_string.FillString('a', 10000);
very_long_string.Write(out);
TTrickyAlignedData tricky_data_out;
memset(&tricky_data_out, 0xAA, sizeof(tricky_data_out));
{
tricky_data_out.a = 11;
tricky_data_out.b = 12;
tricky_data_out.c = 13;
tricky_data_out.d[0] = 14;
tricky_data_out.d[1] = 15;
tricky_data_out.d[2] = 16;
tricky_data_out.e = 17;
memset(tricky_data_out.f, 0, 17);
tricky_data_out.g[0] = 18;
tricky_data_out.g[1] = 19;
tricky_data_out.g[2] = 20;
tricky_data_out.g[3] = 21;
memset(tricky_data_out.h, 0, 13 * sizeof(short));
tricky_data_out.i[0] = 22;
tricky_data_out.i[1] = 23;
tricky_data_out.i[2] = 24;
tricky_data_out.j = 25;
tricky_data_out.k = 26;
tricky_data_out.l = 27;
tricky_data_out.m = 28;
tricky_data_out.n = 29;
tricky_data_out.i64a = 30;
tricky_data_out.o = 31;
tricky_data_out.i64b = 32;
tricky_data_out.p = 33;
tricky_data_out.i64c = 34;
tricky_data_out.q = 35;
tricky_data_out.r = 36;
tricky_data_out.i64d = 37;
tricky_data_out.final = 38;
#if defined (TEST_BIGENDIAN)
TTrickyAlignedData bigend_data = tricky_data_out;
bigend_data.b = BBOp::SwapBytesInt32(bigend_data.b);
bigend_data.c = BBOp::SwapBytesInt32(bigend_data.c);
for (int i = 0; i < 3; ++i) {
bigend_data.d[i] = BBOp::SwapBytesInt16(bigend_data.d[i]);
}
bigend_data.e = BBOp::SwapBytesInt32(bigend_data.e);
for (int i = 0; i < 4; ++i) {
bigend_data.g[i] = BBOp::SwapBytesInt32(bigend_data.g[i]);
}
for (int i = 0; i < 13; ++i) {
bigend_data.h[i] = BBOp::SwapBytesInt16(bigend_data.h[i]);
}
bigend_data.j = BBOp::SwapBytesInt16(bigend_data.j);
bigend_data.k = BBOp::SwapBytesInt32(bigend_data.k);
bigend_data.l = BBOp::SwapBytesInt16(bigend_data.l);
bigend_data.m = BBOp::SwapBytesInt16(bigend_data.m);
bigend_data.n = BBOp::SwapBytesInt32(bigend_data.n);
bigend_data.i64a = BBOp::SwapBytesInt64(bigend_data.i64a);
bigend_data.i64b = BBOp::SwapBytesInt64(bigend_data.i64b);
bigend_data.p = BBOp::SwapBytesInt16(bigend_data.p);
bigend_data.i64c = BBOp::SwapBytesInt64(bigend_data.i64c);
bigend_data.q = BBOp::SwapBytesInt16(bigend_data.q);
bigend_data.r = BBOp::SwapBytesInt16(bigend_data.r);
bigend_data.i64d = BBOp::SwapBytesInt64(bigend_data.i64d);
out->Write(&bigend_data, sizeof(TTrickyAlignedData));
#else
out->Write(&tricky_data_out, sizeof(TTrickyAlignedData));
#endif
}
out->WriteInt32(20);
delete out;
//-------------------------------------------------------------------------
Stream *in = File::OpenFile("test.tmp", AGS::Shared::kFile_Open, AGS::Shared::kFile_Read);
int16_t int16val = in->ReadInt16();
int64_t int64val = in->ReadInt64();
String str1 = String::FromStream(in);
String str2 = String::FromStream(in);
TTrickyAlignedData tricky_data_in;
memset(&tricky_data_in, 0xAA, sizeof(tricky_data_in));
{
AlignedStream as(in, AGS::Shared::kAligned_Read);
tricky_data_in.a = as.ReadInt8();
tricky_data_in.b = as.ReadInt32();
tricky_data_in.c = as.ReadInt32();
as.ReadArrayOfInt16(tricky_data_in.d, 3);
tricky_data_in.e = as.ReadInt32();
as.Read(tricky_data_in.f, 17);
as.ReadArrayOfInt32(tricky_data_in.g, 4);
as.ReadArrayOfInt16(tricky_data_in.h, 13);
as.Read(tricky_data_in.i, 3);
tricky_data_in.j = as.ReadInt16();
tricky_data_in.k = as.ReadInt32();
tricky_data_in.l = as.ReadInt16();
tricky_data_in.m = as.ReadInt16();
tricky_data_in.n = as.ReadInt32();
tricky_data_in.i64a = as.ReadInt64();
tricky_data_in.o = as.ReadInt8();
tricky_data_in.i64b = as.ReadInt64();
tricky_data_in.p = as.ReadInt16();
tricky_data_in.i64c = as.ReadInt64();
tricky_data_in.q = as.ReadInt16();
tricky_data_in.r = as.ReadInt16();
tricky_data_in.i64d = as.ReadInt64();
tricky_data_in.final = as.ReadInt8();
}
int32_t int32val = in->ReadInt32();
delete in;
File::DeleteFile("test.tmp");
//-----------------------------------------------------
// Assertions
assert(int16val == 10);
assert(int64val == -20202);
assert(strcmp(str1, "test.tmp") == 0);
assert(strcmp(str2, very_long_string) == 0);
assert(memcmp(&tricky_data_in, &tricky_data_out, sizeof(TTrickyAlignedData)) == 0);
assert(int32val == 20);
assert(!File::TestReadFile("test.tmp"));
}
} // namespace AGS3

View File

@@ -0,0 +1,276 @@
/* 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/debugging/out.h"
#include "common/scummsys.h"
#include "common/debug.h"
#include "ags/shared/core/platform.h"
#include "ags/shared/gfx/gfx_def.h"
#include "common/scummsys.h"
#include "ags/lib/allegro/color.h"
#include "ags/shared/gfx/bitmap.h"
#include "ags/shared/gfx/image.h"
#include "ags/lib/allegro/surface.h"
#include "ags/shared/debugging/debug_manager.h"
#include "ags/globals.h"
#include "graphics/managed_surface.h"
#include "graphics/pixelformat.h"
namespace AGS3 {
namespace GfxDef = AGS::Shared::GfxDef;
using namespace AGS::Shared;
void Test_GfxSpeed(bool enableSimd, size_t blenderModeStart, size_t blenderModeEnd) {
uint oldSimdFlags = _G(simd_flags);
if (!enableSimd) _G(simd_flags) = AGS3::Globals::SIMD_NONE;
if (enableSimd) debug("SIMD optimizations: true\n");
else debug("SIMD optimizations: false\n");
Bitmap *benchgfx32 = BitmapHelper::CreateBitmap(100, 100, 32);
Bitmap *benchgfx16 = BitmapHelper::CreateBitmapCopy(benchgfx32, 16);
Bitmap *benchgfx8 = BitmapHelper::CreateBitmap(100, 100, 8);
Bitmap *dest32 = BitmapHelper::CreateBitmap(100, 100, 32);
Bitmap *dest16 = BitmapHelper::CreateBitmap(100, 100, 16);
Bitmap *dest8 = BitmapHelper::CreateBitmap(100, 100, 8);
int benchRuns[] = {1000, 10000, 100000};
int blenderModes[] = {kRgbToRgbBlender, kSourceAlphaBlender, kArgbToArgbBlender, kOpaqueBlenderMode, kTintLightBlenderMode};
//const char *modeNames[] = {"RGB to RGB", "Source Alpha", "ARGB to ARGB", "Opaque", "Tint with Light"};
Bitmap *destinations[] = {dest32, dest16, dest8};
Bitmap *graphics[] = {benchgfx32, benchgfx16, benchgfx8};
uint64 time = 0, numIters = 0, timeNotStretched = 0, numItersNotStretched = 0, timeCommon = 0, numItersCommon = 0;
//int bpps[] = {32, 16, 8};
if (blenderModeEnd >= sizeof(blenderModes) / sizeof(blenderModes[0])) blenderModeEnd = (sizeof(blenderModes) / sizeof(blenderModes[0])) - 1;
for (int dest = 0; dest < 3; dest++) {
for (int gfx = 0; gfx < 3; gfx++) {
if (dest == 2 && gfx != 2) continue;
for (size_t mode = blenderModeStart; mode <= blenderModeEnd; mode++) {
for (int runs = 0; (size_t)runs < sizeof(benchRuns)/sizeof(int); runs++) {
uint32 start, end;
_G(_blender_mode) = (AGS3::BlenderMode)blenderModes[mode];
//if (runs == 2) debug("Dest: %d bpp, Gfx: %d bpp, Blender: %s, Stretched: false, Iters: %d\n", bpps[dest], bpps[gfx], modeNames[mode], benchRuns[runs]);
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < benchRuns[runs]; i++)
destinations[dest]->Blit(graphics[gfx], 0, 0, kBitmap_Transparency);
end = std::chrono::high_resolution_clock::now();
timeNotStretched += end - start;
numItersNotStretched += benchRuns[runs];
if (mode == kArgbToArgbBlender || mode == kRgbToRgbBlender || mode == kRgbToArgbBlender || mode == kArgbToRgbBlender) {
timeCommon += end - start;
numItersCommon += benchRuns[runs];
}
time += end - start;
//if (runs == 2) debug("exec time (mills): %u\n\n", end - start);
//if (runs == 2) debug("Dest: %d bpp, Gfx: %d bpp, Blender: %s, Stretched: true, Iters: %d\n", bpps[dest], bpps[gfx], modeNames[mode], benchRuns[runs]);
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < benchRuns[runs]; i++)
destinations[dest]->StretchBlt(graphics[gfx], Rect(0, 0, 99, 99), kBitmap_Transparency);
end = std::chrono::high_resolution_clock::now();
time += end - start;
numIters += benchRuns[runs] * 2;
//if (runs == 2) debug("exec time (mills): %u\n\n", end - start);
}
}
}
}
debug("Over all blender modes, pixel formats, and stretching sizes (%f) avg millis per call.", (double)time / (double)numIters);
debug("Over all blender modes, pixel formats, but only unstretched (%f) avg millis per call.", (double)timeNotStretched / (double)numItersNotStretched);
debug("Over most common blender modes, all pixel formats, but only unstretched (%f) avg millis per call.", (double)timeCommon / (double)numItersCommon);
delete benchgfx32;
delete benchgfx16;
delete benchgfx8;
delete dest32;
delete dest16;
delete dest8;
if (!enableSimd) _G(simd_flags) = oldSimdFlags;
}
void Test_BlenderModes() {
constexpr int depth = 2;
Graphics::ManagedSurface owner(16, 16, Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24));
BITMAP dummy(&owner);
Graphics::ManagedSurface owner16(16, 16, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
BITMAP dummy16(&owner16);
Graphics::ManagedSurface ownerDest(16, 16, Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24));
BITMAP dummyDest(&ownerDest);
Graphics::ManagedSurface ownerDest16(16, 16, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
BITMAP dummyDest16(&ownerDest16);
for (int blenderMode = (int)kSourceAlphaBlender; blenderMode <= (int)kTintLightBlenderMode; blenderMode++) {
_G(_blender_mode) = (BlenderMode)blenderMode;
for (int srcR = 0; srcR < 255; srcR += (1 << (8 - depth))) {
for (int srcG = 0; srcG < 255; srcG += (1 << (8 - depth))) {
for (int srcB = 0; srcB < 255; srcB += (1 << (8 - depth))) {
for (int srcA = 0; srcA < 255; srcA += (1 << (8 - depth))) {
for (int destR = 0; destR < 255; destR += (1 << (8 - depth))) {
for (int destG = 0; destG < 255; destG += (1 << (8 - depth))) {
for (int destB = 0; destB < 255; destB += (1 << (8 - depth))) {
for (int destA = 0; destA < 255; destA += (1 << (8 - depth))) {
for (uint32 alpha = 0; alpha < 255; alpha += (1 << (8 - depth))) {
// First run the non-vectorized version of the code
uint32 controlCol = 0, simdCol = 0;
uint16 control2bppCol = 0, simd2bppCol = 0;
uint8 a, r, g, b, a16, r16, g16, b16;
a = r = g = b = a16 = r16 = g16 = b16 = 0;
auto printInfo = [&]() {
debug("src argb: %d, %d, %d, %d dest argb: %d, %d, %d, %d a: %d", srcA, srcR, srcG, srcB, destA, destR, destG, destB, alpha);
switch ((BlenderMode)blenderMode) {
case kSourceAlphaBlender: debug("blenderMode: kSourceAlphaBlender"); break;
case kArgbToArgbBlender: debug("blenderMode: kArgbToArgbBlender"); break;
case kArgbToRgbBlender: debug("blenderMode: kArgbToRgbBlender"); break;
case kRgbToArgbBlender: debug("blenderMode: kRgbToArgbBlender"); break;
case kRgbToRgbBlender: debug("blenderMode: kRgbToRgbBlender"); break;
case kAlphaPreservedBlenderMode: debug("blenderMode: kAlphaPreservedBlenderMode"); break;
case kOpaqueBlenderMode: debug("blenderMode: kOpaqueBlenderMode"); break;
case kAdditiveBlenderMode: debug("blenderMode: kAdditiveBlenderMode"); break;
case kTintBlenderMode: debug("blenderMode: kTintBlenderMode"); break;
case kTintLightBlenderMode: debug("blenderMode: kTintLightBlenderMode"); break;
}
debug("controlCol %x argb: %d, %d, %d, %d", controlCol, a, r, g, b);
debug("simdCol %x argb: %d, %d, %d, %d", simdCol, (simdCol >> 24), ((simdCol >> 16) & 0xff), ((simdCol >> 8) & 0xff), (simdCol & 0xff));
debug("control2bppCol %x rgb: %d, %d, %d", control2bppCol, r16, g16, b16);
debug("simd2bppCol %x rgb: %d, %d, %d", simd2bppCol, (simd2bppCol >> 11), ((simd2bppCol >> 5) & 0x3f), (simd2bppCol & 0x1f));
};
uint oldSimdFlags = _G(simd_flags);
_G(simd_flags) = AGS3::Globals::SIMD_NONE;
*(uint32 *)dummy.getBasePtr(0, 0) = dummy.format.ARGBToColor(srcA, srcR, srcG, srcB);
*(uint32 *)dummyDest.getBasePtr(0, 0) = dummyDest.format.ARGBToColor(destA, destR, destG, destB);
dummyDest.draw(&dummy, Common::Rect(16, 16), 0, 0, false, false, false, alpha);
controlCol = dummyDest.getpixel(0, 0);
dummyDest.format.colorToARGB(dummyDest.getpixel(0, 0), a, r, g, b);
*(uint16 *)dummy16.getBasePtr(0, 0) = dummy16.format.ARGBToColor(srcA, srcR, srcG, srcB);
*(uint16 *)dummyDest16.getBasePtr(0, 0) = dummyDest16.format.ARGBToColor(destA, destR, destG, destB);
dummyDest16.draw(&dummy16, Common::Rect(16, 16), 0, 0, false, false, false, alpha);
control2bppCol = dummyDest16.getpixel(0, 0);
dummyDest16.format.colorToARGB(dummyDest16.getpixel(0, 0), a16, r16, g16, b16);
a16 >>= 3; r16 >>= 3; g16 >>= 2; b16 >>= 3;
_G(simd_flags) = oldSimdFlags;
*(uint32 *)dummy.getBasePtr(0, 0) = dummy.format.ARGBToColor(srcA, srcR, srcG, srcB);
*(uint32 *)dummyDest.getBasePtr(0, 0) = dummyDest.format.ARGBToColor(destA, destR, destG, destB);
dummyDest.draw(&dummy, Common::Rect(16, 16), 0, 0, false, false, false, alpha);
simdCol = dummyDest.getpixel(0, 0);
*(uint16 *)dummy16.getBasePtr(0, 0) = dummy16.format.ARGBToColor(srcA, srcR, srcG, srcB);
*(uint16 *)dummyDest16.getBasePtr(0, 0) = dummyDest16.format.ARGBToColor(destA, destR, destG, destB);
dummyDest16.draw(&dummy16, Common::Rect(16, 16), 0, 0, false, false, false, alpha);
simd2bppCol = dummyDest16.getpixel(0, 0);
int tolerance, tolerance16;
switch ((BlenderMode)blenderMode) {
// These need to be IDENTICAL for lamplight city to work
// It would be nice to get tolerance16 down to 0 though...
case kRgbToRgbBlender:
case kArgbToRgbBlender:
case kSourceAlphaBlender:
case kAlphaPreservedBlenderMode:
tolerance = 0;
tolerance16 = 1;
break;
// These can be 1 or 2 off, as long as they look the same
case kArgbToArgbBlender:
case kRgbToArgbBlender:
case kOpaqueBlenderMode:
case kAdditiveBlenderMode:
tolerance = 1;
tolerance16 = 1;
break;
case kTintBlenderMode:
case kTintLightBlenderMode:
tolerance = 2;
tolerance16 = 1;
break;
default:
tolerance = 0;
}
if (std::abs((int)a - (int)(simdCol >> 24)) > tolerance) {
printInfo();
assert(false && "a is over the tolerance");
}
if (std::abs((int)r - (int)((simdCol >> 16) & 0xff)) > tolerance) {
printInfo();
assert(false && "r is over the tolerance");
}
if (std::abs((int)g - (int)((simdCol >> 8) & 0xff)) > tolerance) {
printInfo();
assert(false && "g is over the tolerance");
}
if (std::abs((int)b - (int)(simdCol & 0xff)) > tolerance) {
printInfo();
assert(false && "b is over the tolerance");
}
if (std::abs((int)b16 - (int)(simd2bppCol & 0x1f)) > tolerance16) {
printInfo();
assert(false && "b16 is over the tolerance");
}
if (std::abs((int)g16 - (int)((simd2bppCol >> 5) & 0x3f)) > tolerance16) {
printInfo();
assert(false && "g16 is over the tolerance");
}
if (std::abs((int)r16 - (int)(simd2bppCol >> 11)) > tolerance16) {
printInfo();
assert(false && "r16 is over the tolerance");
}
}
}
}
}
}
}
}
}
}
}
}
void Test_GfxTransparency() {
// Test that every transparency which is a multiple of 10 is converted
// forth and back without losing precision
const size_t arr_sz = 11;
const int trans100[arr_sz] = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
int trans255[arr_sz] = { 0 };
int trans100_back[arr_sz] = { 0 };
for (size_t i = 0; i < arr_sz; ++i) {
trans255[i] = GfxDef::Trans100ToLegacyTrans255(trans100[i]);
trans100_back[i] = GfxDef::LegacyTrans255ToTrans100(trans255[i]);
assert(trans100[i] == trans100_back[i]);
}
}
void Test_Gfx() {
Test_GfxTransparency();
#if (defined(SCUMMVM_AVX2) || defined(SCUMMVM_SSE2) || defined(SCUMMVM_NEON)) && defined(SLOW_TESTS)
Test_BlenderModes();
// This could take a LONG time
Test_GfxSpeed(true, kSourceAlphaBlender, kTintLightBlenderMode);
Test_GfxSpeed(false, kSourceAlphaBlender, kTintLightBlenderMode);
#endif
}
} // namespace AGS3

View File

@@ -0,0 +1,339 @@
/* 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/core/platform.h"
#include "common/std/algorithm.h"
//#include "ags/shared/debugging/assert.h"
// File not present??
#include "common/scummsys.h"
#include "ags/shared/util/file.h"
#include "ags/shared/util/ini_util.h"
#include "ags/shared/util/ini_file.h"
#include "ags/shared/util/stream.h"
namespace AGS3 {
using namespace AGS::Shared;
#if AGS_PLATFORM_OS_WINDOWS
#define ENDL "\r\n"
#else
#define ENDL "\n"
#endif
const char *IniFileText = ""
"global_item=global_value" ENDL
"[section1]" ENDL
"item1" ENDL
"//this is comment" ENDL
"item2=" ENDL
"item3=value" ENDL
"item4=another value" ENDL
"[this_section_should_be_deleted]" ENDL
"item1=value1" ENDL
"item2=value2" ENDL
";this is comment" ENDL
"[section3]" ENDL
"item_to_be_deleted=value" ENDL
"item_to_be_kept=another value" ENDL
" [ section4 ] " ENDL
" item1 = value " ENDL;
const char *IniFileText2 = ""
"global_item=global_value" ENDL
"[section1]" ENDL
"item1=value1" ENDL
"//this is comment" ENDL
"item2=value2" ENDL
"item3=value3" ENDL
"new_item=new_value" ENDL
"[section3]" ENDL
"item_to_be_kept=another value" ENDL
" [ section4 ] " ENDL
"new_item1=new_value1" ENDL
" item1 = value " ENDL
"new_item2=new_value2" ENDL
"[section5]" ENDL
"item5_1=value5_1" ENDL
"item5_2=value5_2" ENDL
"item5_3=value5_3" ENDL;
bool operator==(const StringOrderMap &lhs, const StringOrderMap &rhs) {
if (lhs.size() != rhs.size())
return false;
StringOrderMap::const_iterator it1 = lhs.begin();
StringOrderMap::const_iterator it2 = rhs.begin();
for (; it1 != lhs.end(); ++it1, ++it2) {
if (it1->_key || it2->_key || it1->_value != it2->_value)
return false;
}
return true;
}
bool operator==(const ConfigTree &lhs, const ConfigTree &rhs) {
if (lhs.size() != rhs.size())
return false;
ConfigTree::const_iterator it1 = lhs.begin();
ConfigTree::const_iterator it2 = rhs.begin();
for (; it1 != lhs.end(); ++it1, ++it2) {
if (it1->_key || it2->_key || !(it1->_value == it2->_value))
return false;
}
return true;
}
void Test_IniFile() {
Stream *fs = File::CreateFile("test.ini");
fs->Write(IniFileText, strlen(IniFileText));
delete fs;
IniFile ini;
fs = File::OpenFileRead("test.ini");
ini.Read(fs);
delete fs;
// there are explicit sections and 1 implicit global one
const size_t section_count = 5;
// Test reading from the custom ini file
{
assert(ini.GetSectionCount() == section_count);
IniFile::ConstSectionIterator sec = ini.CBegin();
assert(sec->GetItemCount() == 1u);
IniFile::ConstItemIterator item = sec->CBegin();
assert(item->GetKey() == "global_item");
assert(item->GetValue() == "global_value");
++sec;
assert(sec->GetName() == "section1");
assert(sec->GetItemCount() == 5u);
item = sec->CBegin();
assert(item->GetKey() == "item1");
assert(item->GetValue() == "");
++item;
assert(item->GetLine() == "//this is comment");
++item;
assert(item->GetKey() == "item2");
assert(item->GetValue() == "");
++item;
assert(item->GetKey() == "item3");
assert(item->GetValue() == "value");
++item;
assert(item->GetKey() == "item4");
assert(item->GetValue() == "another value");
++sec;
assert(sec->GetName() == "this_section_should_be_deleted");
assert(sec->GetItemCount() == 3u);
item = sec->CBegin();
assert(item->GetKey() == "item1");
assert(item->GetValue() == "value1");
++item;
assert(item->GetKey() == "item2");
assert(item->GetValue() == "value2");
++item;
assert(item->GetLine() == ";this is comment");
++sec;
assert(sec->GetName() == "section3");
assert(sec->GetItemCount() == 2u);
item = sec->CBegin();
assert(item->GetKey() == "item_to_be_deleted");
assert(item->GetValue() == "value");
++item;
assert(item->GetKey() == "item_to_be_kept");
assert(item->GetValue() == "another value");
++sec;
assert(sec->GetName() == "section4");
assert(sec->GetItemCount() == 1u);
item = sec->CBegin();
assert(item->GetKey() == "item1");
assert(item->GetValue() == "value");
}
// Test altering INI data and saving to file
{
// Modiying item values
IniFile::SectionIterator sec = ini.Begin();
++sec;
IniFile::ItemIterator item = sec->Begin();
item->SetValue("value1");
++item;
++item;
item->SetValue("value2");
++item;
item->SetValue("value3");
++item;
item->SetKey("new_item");
item->SetValue("new_value");
// Removing a section
sec = ini.Begin();
++sec;
++sec;
ini.RemoveSection(sec);
assert(ini.GetSectionCount() == section_count - 1);
// Removing an item
sec = ini.Begin();
++sec;
++sec;
assert(sec->GetName() == "section3");
item = sec->Begin();
assert(item->GetKey() == "item_to_be_deleted");
sec->EraseItem(item);
// Inserting new items
++sec;
assert(sec->GetName() == "section4");
ini.InsertItem(sec, sec->Begin(), "new_item1", "new_value1");
ini.InsertItem(sec, sec->End(), "new_item2", "new_value2");
// Append new section
sec = ini.InsertSection(ini.End(), "section5");
ini.InsertItem(sec, sec->End(), "item5_1", "value5_1");
ini.InsertItem(sec, sec->End(), "item5_2", "value5_2");
ini.InsertItem(sec, sec->End(), "item5_3", "value5_3");
fs = File::CreateFile("test.ini");
ini.Write(fs);
delete fs;
fs = File::OpenFileRead("test.ini");
String ini_content;
ini_content.ReadCount(fs, static_cast<size_t>(fs->GetLength()));
assert(ini_content == IniFileText2);
}
// Test creating KeyValueTree from existing ini file
{
ConfigTree tree;
IniUtil::Read("test.ini", tree);
assert(tree.size() == 5u);
assert(tree.find("") != tree.end()); // global section
assert(tree.find("section1") != tree.end());
assert(tree.find("section3") != tree.end());
assert(tree.find("section4") != tree.end());
assert(tree.find("section5") != tree.end());
StringOrderMap &sub_tree = tree[""];
assert(sub_tree.size() == 1u);
assert(sub_tree.find("global_item") != sub_tree.end());
assert(sub_tree["global_item"] == "global_value");
sub_tree = tree["section1"];
assert(sub_tree.size() == 4u);
assert(sub_tree.find("item1") != sub_tree.end());
assert(sub_tree.find("item2") != sub_tree.end());
assert(sub_tree.find("item3") != sub_tree.end());
assert(sub_tree.find("new_item") != sub_tree.end());
assert(sub_tree["item1"] == "value1");
assert(sub_tree["item2"] == "value2");
assert(sub_tree["item3"] == "value3");
assert(sub_tree["new_item"] == "new_value");
sub_tree = tree["section3"];
assert(sub_tree.size() == 1u);
assert(sub_tree.find("item_to_be_kept") != sub_tree.end());
assert(sub_tree["item_to_be_kept"] == "another value");
sub_tree = tree["section4"];
assert(sub_tree.size() == 3u);
assert(sub_tree.find("new_item1") != sub_tree.end());
assert(sub_tree.find("item1") != sub_tree.end());
assert(sub_tree.find("new_item2") != sub_tree.end());
assert(sub_tree["new_item1"] == "new_value1");
assert(sub_tree["item1"] == "value");
assert(sub_tree["new_item2"] == "new_value2");
sub_tree = tree["section5"];
assert(sub_tree.size() == 3u);
assert(sub_tree.find("item5_1") != sub_tree.end());
assert(sub_tree.find("item5_2") != sub_tree.end());
assert(sub_tree.find("item5_3") != sub_tree.end());
assert(sub_tree["item5_1"] == "value5_1");
assert(sub_tree["item5_2"] == "value5_2");
assert(sub_tree["item5_3"] == "value5_3");
}
// Test self-serialization
ConfigTree tree1;
{
ConfigTree tree2;
// construct the tree
{
StringOrderMap &audio_tree = tree1["audio"];
audio_tree["volume"] = "100.0";
audio_tree["driver"] = "midi";
StringOrderMap &video_tree = tree1["video"];
video_tree["gfx_mode"] = "standard mode";
video_tree["gamma"] = "1.0";
video_tree["vsync"] = "false";
}
IniUtil::Write("test.ini", tree1);
IniUtil::Read("test.ini", tree2);
// Assert, that tree2 has exactly same items as tree1
assert(tree1 == tree2);
}
// Test merging
{
ConfigTree tree3;
ConfigTree tree4;
// Try merging altered tree into existing file
tree3 = tree1;
{
StringOrderMap &audio_tree = tree3["audio"];
audio_tree["extra_option1"] = "extra value 1";
audio_tree["extra_option2"] = "extra value 2";
audio_tree["extra_option3"] = "extra value 3";
StringOrderMap &video_tree = tree3["video"];
video_tree["gfx_mode"] = "alternate mode";
video_tree["gamma"] = "2.0";
StringOrderMap &new_tree = tree3["other1"];
new_tree["item1_1"] = "value1_1";
new_tree["item1_2"] = "value1_2";
new_tree["item1_3"] = "value1_3";
StringOrderMap &new_tree2 = tree3["other2"];
new_tree2["item2_1"] = "value2_1";
new_tree2["item2_2"] = "value2_2";
new_tree2["item2_3"] = "value2_3";
}
IniUtil::Merge("test.ini", tree3);
IniUtil::Read("test.ini", tree4);
// Assert, that tree4 has all the items from tree3
assert(tree3 == tree4);
}
File::DeleteFile("test.ini");
}
} // namespace AGS3

View File

@@ -0,0 +1,70 @@
/* 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/core/platform.h"
//#include "ags/shared/debugging/assert.h"
// File not present??
#include "common/scummsys.h"
#include "ags/shared/util/scaling.h"
namespace AGS3 {
using namespace AGS::Shared;
//using namespace AGS::Engine;
void Test_Scaling(int src, int dst) {
int x;
AxisScaling sc;
sc.Init(src, dst);
x = sc.ScalePt(0);
assert(x == 0);
x = sc.ScalePt(src);
assert(x == dst);
x = sc.UnScalePt(dst);
assert(x == src);
}
void Test_Math() {
Test_Scaling(100, 100);
Test_Scaling(100, 1000);
Test_Scaling(320, 1280);
Test_Scaling(200, 400);
Test_Scaling(1000, 100);
Test_Scaling(1280, 320);
Test_Scaling(400, 200);
Test_Scaling(300, 900);
Test_Scaling(100, 700);
Test_Scaling(200, 2200);
Test_Scaling(900, 300);
Test_Scaling(700, 100);
Test_Scaling(2200, 200);
for (int i = 250; i < 2000; i += 25) {
Test_Scaling(200, i);
Test_Scaling(i, 200);
}
}
} // namespace AGS3

View File

@@ -0,0 +1,92 @@
/* 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/>.
*
*/
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#include "ags/shared/core/platform.h"
#include "ags/shared/util/memory.h"
//#include "ags/shared/debugging/assert.h"
// File not present??
#include "common/scummsys.h"
namespace AGS3 {
using namespace AGS::Shared;
void Test_Memory() {
int16_t i16 = (int16_t)0xABCD;
int32_t i32 = (int32_t)0xABCDEF12;
int64_t i64 = (int64_t)0xABCDEF1234567890;
assert(BBOp::SwapBytesInt16(i16) == (int16_t)0xCDAB);
assert(BBOp::SwapBytesInt32(i32) == (int32_t)0x12EFCDABu);
assert(BBOp::SwapBytesInt64(i64) == (int64_t)0x9078563412EFCDABul);
#if defined (BITBYTE_BIG_ENDIAN)
assert(BBOp::Int16FromLE(i16) == (int16_t)0xCDAB);
assert(BBOp::Int32FromLE(i32) == (int32_t)0x12EFCDABu);
assert(BBOp::Int64FromLE(i64) == (int64_t)0x9078563412EFCDABul);
assert(BBOp::Int16FromBE(i16) == (int16_t)0xABCD);
assert(BBOp::Int32FromBE(i32) == (int32_t)0xABCDEF12);
assert(BBOp::Int64FromBE(i64) == (int64_t)0xABCDEF1234567890);
#else
assert(BBOp::Int16FromLE(i16) == (int16_t)0xABCD);
assert(BBOp::Int32FromLE(i32) == (int32_t)0xABCDEF12);
assert(BBOp::Int64FromLE(i64) == (int64_t)0xABCDEF1234567890);
assert(BBOp::Int16FromBE(i16) == (int16_t)0xCDAB);
assert(BBOp::Int32FromBE(i32) == (int32_t)0x12EFCDABu);
assert(BBOp::Int64FromBE(i64) == (int64_t)0x9078563412EFCDABul);
#endif
int16_t dst_i16 = (int16_t)0xABCD;
int32_t dst_i32 = (int32_t)0xABCDEF12;
int64_t dst_i64 = (int64_t)0xABCDEF1234567890;
void *p_i16 = &dst_i16;
void *p_i32 = &dst_i32;
void *p_i64 = &dst_i64;
#if defined (TEST_BIGENDIAN)
dst_i16 = BBOp::SwapBytesInt16(dst_i16);
dst_i32 = BBOp::SwapBytesInt32(dst_i32);
dst_i64 = BBOp::SwapBytesInt64(dst_i64);
#endif
assert(Memory::ReadInt16(p_i16) == (int16_t)0xABCD);
assert(Memory::ReadInt32(p_i32) == (int32_t)0xABCDEF12);
assert(Memory::ReadInt64(p_i64) == (int64_t)0xABCDEF1234567890);
Memory::WriteInt16(p_i16, (int16_t)0xCDAB);
Memory::WriteInt32(p_i32, (int32_t)0x12EFCDAB);
Memory::WriteInt64(p_i64, (int64_t)0x9078563412EFCDAB);
#if defined (TEST_BIGENDIAN)
dst_i16 = BBOp::SwapBytesInt16(dst_i16);
dst_i32 = BBOp::SwapBytesInt32(dst_i32);
dst_i64 = BBOp::SwapBytesInt64(dst_i64);
#endif
assert(dst_i16 == (int16_t)0xCDAB);
assert(dst_i32 == (int32_t)0x12EFCDAB);
assert(dst_i64 == (int64_t)0x9078563412EFCDAB);
}
} // namespace AGS3

View File

@@ -0,0 +1,135 @@
/* 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/core/platform.h"
//include <string.h>
#include "ags/shared/ac/game_version.h"
//#include "ags/shared/debugging/assert.h"
// File not present??
#include "common/scummsys.h"
#include "ags/engine/script/script_api.h"
#include "ags/engine/script/runtime_script_value.h"
#include "ags/globals.h"
namespace AGS3 {
const char *ScriptVSprintf__(char *buffer, size_t buf_length, const char *format, ...) {
va_list args;
va_start(args, format);
const char *res_buffer = ScriptVSprintf(buffer, buf_length, format, args);
va_end(args);
return res_buffer;
}
void Test_ScriptSprintf() {
const int argi = 123;
const float argf = 0.456F;
const char *argcc = "string literal";
RuntimeScriptValue params[10];
params[0].SetInt32(argi);
params[1].SetFloat(argf);
params[2].SetStringLiteral(argcc);
char ScSfBuffer[STD_BUFFER_SIZE];
//
// Called-from-script variant
//
// Correct format, extra placeholder
const char *result =
ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE,
"testing ScriptSprintf:\nThis is int: %10d\nThis is float: %.4f\nThis is string: '%s'\nThis placeholder will be ignored: %d",
params, 3);
assert(strcmp(result, "testing ScriptSprintf:\nThis is int: 123\nThis is float: 0.4560\nThis is string: 'string literal'\nThis placeholder will be ignored: %d") == 0);
// Literal percent sign
result = ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE, "%d%%", params, 3);
assert(strcmp(result, "123%") == 0);
result = ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE, "123%%", NULL, 0);
assert(strcmp(result, "123%") == 0);
result = ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE, "%%5d%%0.5f%%s", params, 3);
assert(strcmp(result, "%5d%0.5f%s") == 0);
// Invalid format
result = ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE, "%zzzzzz", params, 3);
assert(strcmp(result, "%zzzzzz") == 0);
result = ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE, "%12.34%d", params, 3);
assert(strcmp(result, "%12.34123") == 0);
// Not enough arguments
result = ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE, "%5d%0.5f%s", params, 0);
assert(strcmp(result, "%5d%0.5f%s") == 0);
// Not enough buffer space
result = ScriptSprintf(ScSfBuffer, 9, "12345678%d", params, 3);
assert(strcmp(result, "12345678") == 0);
result = ScriptSprintf(ScSfBuffer, 11, "12345678%d", params, 3);
assert(strcmp(result, "1234567812") == 0);
// Not enough buffer space and not enough params
result = ScriptSprintf(ScSfBuffer, 10, "12345678%d", params, 0);
assert(strcmp(result, "12345678%") == 0);
result = ScriptSprintf(ScSfBuffer, 11, "12345678%d", params, 0);
assert(strcmp(result, "12345678%d") == 0);
// Test null string pointer in backward-compatibility mode
_G(loaded_game_file_version) = kGameVersion_312;
params[0].SetStringLiteral(NULL);
result = ScriptSprintf(ScSfBuffer, 10, "A%sB", params, 1);
assert(strcmp(result, "A(null)B") == 0);
_G(loaded_game_file_version) = kGameVersion_Undefined;
//
// Called-from-plugin variant
// Note that since this is variadic function, number of parameters must
// always be equal or higher than number of placeholders in buffer string.
//
// Correct format, matching number of arguments
result =
ScriptVSprintf__(ScSfBuffer, STD_BUFFER_SIZE,
"testing ScriptVSprintf:\nThis is int: %10d\nThis is float: %.4f\nThis is string: '%s'\n",
argi, argf, argcc);
assert(strcmp(result, "testing ScriptVSprintf:\nThis is int: 123\nThis is float: 0.4560\nThis is string: 'string literal'\n") == 0);
// Literal percent sign
result = ScriptVSprintf__(ScSfBuffer, STD_BUFFER_SIZE, "%d%%", argi);
assert(strcmp(result, "123%") == 0);
result = ScriptVSprintf__(ScSfBuffer, STD_BUFFER_SIZE, "123%%");
assert(strcmp(result, "123%") == 0);
result = ScriptVSprintf__(ScSfBuffer, STD_BUFFER_SIZE, "%%5d%%0.5f%%s");
assert(strcmp(result, "%5d%0.5f%s") == 0);
// Invalid format
result = ScriptVSprintf__(ScSfBuffer, STD_BUFFER_SIZE, "%zzzzzz", argi, argf, argcc);
assert(strcmp(result, "%zzzzzz") == 0);
result = ScriptVSprintf__(ScSfBuffer, STD_BUFFER_SIZE, "%12.34%d", argi, argf, argcc);
assert(strcmp(result, "%12.34123") == 0);
// Not enough buffer space
result = ScriptVSprintf__(ScSfBuffer, 9, "12345678%d", argi, argf, argcc);
assert(strcmp(result, "12345678") == 0);
result = ScriptVSprintf__(ScSfBuffer, 11, "12345678%d", argi, argf, argcc);
assert(strcmp(result, "1234567812") == 0);
// Test null string pointer in backward-compatibility mode
_G(loaded_game_file_version) = kGameVersion_312;
result = ScriptVSprintf__(ScSfBuffer, 10, "A%sB", NULL);
assert(strcmp(result, "A(null)B") == 0);
_G(loaded_game_file_version) = kGameVersion_Undefined;
}
} // namespace AGS3

View File

@@ -0,0 +1,512 @@
/* 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/debugging/assert.h"
// File not present??
#include "common/scummsys.h"
#include "ags/shared/core/platform.h"
#include "common/std/vector.h"
#include "ags/shared/util/path.h"
#include "ags/shared/util/string.h"
#include "ags/shared/debugging/debug_manager.h"
namespace AGS3 {
using namespace AGS::Shared;
void Test_Path() {
assert(Path::IsSameOrSubDir(".", "dir1/") == true);
assert(Path::IsSameOrSubDir(".", "dir1/dir2/dir3/") == true);
assert(Path::IsSameOrSubDir(".", "dir1/../") == true);
assert(Path::IsSameOrSubDir(".", "dir1/dir2/../../") == true);
assert(Path::IsSameOrSubDir(".", "dir1/../dir2/../dir3/") == true);
assert(Path::IsSameOrSubDir(".", "..dir/") == true);
assert(Path::IsSameOrSubDir(".", "../") == false);
assert(Path::IsSameOrSubDir(".", "../") == false);
assert(Path::IsSameOrSubDir(".", "/dir1/") == false);
assert(Path::IsSameOrSubDir(".", "dir1/../../") == false);
assert(Path::IsSameOrSubDir(".", "dir1/../dir2/../../dir3/") == false);
}
void Test_String() {
// Test string's internal work
#if defined(AGS_PLATFORM_TEST) && AGS_PLATFORM_TEST
{
String s1 = "abcdefghijklmnop";
String s2 = s1;
String s3 = s1;
assert(s1.GetRefCount() == 3);
assert(s1.GetBuffer() == s2.GetBuffer());
assert(s2.GetBuffer() == s3.GetBuffer());
size_t cap1 = s1.GetCapacity();
assert(cap1 == s1.GetLength());
s2.TruncateToLeft(10);
assert(cap1 == s2.GetCapacity());
s3.TruncateToRight(10);
assert(cap1 == s3.GetCapacity());
assert(s1.GetRefCount() == 1);
s2.AppendChar('z');
assert(cap1 == s2.GetCapacity());
s3.Append("1234");
assert(cap1 == s3.GetCapacity());
s3.Append("1234567890123");
assert(27 == s3.GetCapacity());
s3.Append("1234567890123");
assert(40 == s3.GetCapacity());
s3.Append("1234567890123");
assert(60 == s3.GetCapacity());
String s4 = "12345678901234567890";
const char *cstr = s4.GetCStr();
s4.ClipLeft(10);
assert(s4.GetCStr() == cstr + 10);
s4.Prepend("12345");
assert(s4.GetCStr() == cstr + 5);
s4.Append("12345");
assert(s4.GetCStr() == cstr);
assert(strcmp(s4, "12345123456789012345") == 0);
}
#endif
// Test Compare
{
String s1 = "abcdabcdabcd";
String s2 = "abcdbfghijklmn";
int cmp1 = s1.Compare(s2);
int cmp2 = s1.CompareLeft("abcd");
int cmp3 = s1.CompareLeft("abcdxxx");
int cmp4 = s1.CompareLeft("abcdxxx", 4);
int cmp5 = s1.CompareMid(s2, 2, 4);
int cmp6 = s1.CompareMid(s2, 8, 4);
int cmp7 = s1.CompareMid(s2, 8, 9);
int cmp8 = s1.CompareLeft("abcdabcdabcdxxxx");
int cmp9 = s1.CompareMid("ab", 8);
int cmp10 = s1.CompareMid("ab", 8, 4);
int cmp11 = s1.CompareRight("abcd");
int cmp12 = s1.CompareRight("bcdxxx", 3);
int cmp13 = s1.CompareRight("abc", 4);
int cmp14 = s1.CompareRight("abcdxxxx");
assert(cmp1 < 0);
assert(cmp2 == 0);
assert(cmp3 < 0);
assert(cmp4 == 0);
assert(cmp5 > 0);
assert(cmp6 == 0);
assert(cmp7 < 0);
assert(cmp8 < 0);
assert(cmp9 == 0);
assert(cmp10 > 0);
assert(cmp11 == 0);
assert(cmp12 == 0);
assert(cmp13 > 0);
assert(cmp14 < 0);
}
// Test FindChar
{
String s1 = "findsomethinginhere";
String s2 = "stringtofindsomethinginside";
String s3 = "findsomethinginherex";
String s4 = "xstringtofindsomethinginside";
String s5;
size_t find1 = s1.FindChar('o');
size_t find2 = s2.FindCharReverse('o');
size_t find3 = s1.FindChar('x');
size_t find4 = s2.FindCharReverse('x');
size_t find5 = s3.FindChar('x');
size_t find6 = s4.FindCharReverse('x');
size_t find7 = s5.FindChar('x');
size_t find8 = s5.FindCharReverse('x');
size_t find9 = s1.FindChar('i', 2);
size_t find10 = s1.FindCharReverse('i', 12);
assert(find1 == 5LLU);
assert(find2 == 13LLU);
assert(find3 == -1LLU);
assert(find4 == -1LLU);
assert(find5 == 19LLU);
assert(find6 == 0LLU);
assert(find7 == -1LLU);
assert(find8 == -1LLU);
assert(find9 == 10LLU);
assert(find10 == 10LLU);
}
// Test GetAt
{
String s1 = "abcdefghijklmnop";
String s2;
char c1 = s1.GetAt(0);
char c2 = s1.GetAt(15);
char c3 = s1.GetAt(16);
char c4 = s2.GetAt(0);
assert(c1 == 'a');
assert(c2 == 'p');
assert(c3 == 0);
assert(c4 == 0);
}
// Test ToInt
{
String s1;
String s2 = "100";
String s3 = "202aaa";
String s4 = "aaa333";
int i1 = s1.ToInt();
int i2 = s2.ToInt();
int i3 = s3.ToInt();
int i4 = s4.ToInt();
assert(i1 == 0);
assert(i2 == 100);
assert(i3 == 202);
assert(i4 == 0);
}
// Test Left/Right/Mid
{
String s1 = "this is a string to be split";
String s2 = s1.Left(4);
String s3 = s1.Left(100);
String s4 = s1.Mid(10);
String s5 = s1.Mid(10, 6);
String s6 = s1.Mid(0, 200);
String s7 = s1.Right(5);
String s8 = s1.Right(100);
String s9 = s1.Left(0);
String s10 = s1.Mid((size_t) - 1, 0);
String s11 = s1.Right(0);
assert(strcmp(s2, "this") == 0);
assert(strcmp(s3, "this is a string to be split") == 0);
assert(strcmp(s4, "string to be split") == 0);
assert(strcmp(s5, "string") == 0);
assert(strcmp(s6, "this is a string to be split") == 0);
assert(strcmp(s7, "split") == 0);
assert(strcmp(s8, "this is a string to be split") == 0);
assert(strcmp(s9, "") == 0);
assert(strcmp(s10, "") == 0);
assert(strcmp(s11, "") == 0);
}
// Test Section
{
String s = "_123_567_";
size_t from;
size_t to;
assert(s.FindSection('_', 0, 0, true, true, from, to));
assert(from == 0 && to == 0);
assert(s.FindSection('_', 0, 0, false, true, from, to));
assert(from == 0 && to == 0);
assert(s.FindSection('_', 0, 0, true, false, from, to));
assert(from == 0 && to == 1);
assert(s.FindSection('_', 0, 0, false, false, from, to));
assert(from == 0 && to == 1);
assert(s.FindSection('_', 3, 3, true, true, from, to));
assert(from == 9 && to == 9);
assert(s.FindSection('_', 3, 3, false, true, from, to));
assert(from == 8 && to == 9);
assert(s.FindSection('_', 3, 3, true, false, from, to));
assert(from == 9 && to == 9);
assert(s.FindSection('_', 3, 3, false, false, from, to));
assert(from == 8 && to == 9);
assert(s.FindSection('_', 1, 1, true, true, from, to));
assert(from == 1 && to == 4);
assert(s.FindSection('_', 1, 1, false, true, from, to));
assert(from == 0 && to == 4);
assert(s.FindSection('_', 1, 1, true, false, from, to));
assert(from == 1 && to == 5);
assert(s.FindSection('_', 1, 1, false, false, from, to));
assert(from == 0 && to == 5);
}
// Test Append
{
String s1 = "a string to enlarge - ";
s1.Append("make it bigger");
assert(strcmp(s1, "a string to enlarge - make it bigger") == 0);
s1.AppendChar('!');
assert(strcmp(s1, "a string to enlarge - make it bigger!") == 0);
s1.AppendChar(' ');
assert(strcmp(s1, "a string to enlarge - make it bigger! ") == 0);
s1.Append("much much bigger!");
assert(strcmp(s1, "a string to enlarge - make it bigger! much much bigger!") == 0);
}
// Test Clip
{
String str1 = "long truncateable string";
String str2 = str1;
String str3 = str1;
String str4 = str1;
String str5 = str1;
str1.ClipLeft(4);
str2.ClipRight(6);
str3.ClipMid(5, 12);
str4.ClipMid(5, 0);
str5.ClipMid(0);
assert(strcmp(str1, " truncateable string") == 0);
assert(strcmp(str2, "long truncateable ") == 0);
assert(strcmp(str3, "long string") == 0);
assert(strcmp(str4, "long truncateable string") == 0);
assert(strcmp(str5, "") == 0);
}
// Test ClipSection
{
String str1 = "C:\\Games\\AGS\\MyNewGame";
String str2 = str1;
String str3 = str1;
String str4 = str1;
String str5 = str1;
String str6 = str1;
String str7 = str1;
String str8 = str1;
String str9 = str1;
String str10 = str1;
String str11 = str1;
str1.ClipLeftSection('\\');
str2.ClipLeftSection('\\', false);
str3.ClipRightSection('\\');
str4.ClipRightSection('\\', false);
str5.ClipSection('\\', 1, 2);
str6.ClipSection('\\', 1, 2, false, false);
str7.ClipSection('|', 1, 2);
str8.ClipSection('\\', 0, 2);
str9.ClipSection('\\', 1, 3);
str10.ClipSection('\\', 3, 1);
str11.ClipSection('\\', 0, 4);
assert(strcmp(str1, "Games\\AGS\\MyNewGame") == 0);
assert(strcmp(str2, "\\Games\\AGS\\MyNewGame") == 0);
assert(strcmp(str3, "C:\\Games\\AGS") == 0);
assert(strcmp(str4, "C:\\Games\\AGS\\") == 0);
assert(strcmp(str5, "C:MyNewGame") == 0);
assert(strcmp(str6, "C:\\\\MyNewGame") == 0);
assert(strcmp(str7, "C:\\Games\\AGS\\MyNewGame") == 0);
assert(strcmp(str8, "MyNewGame") == 0);
assert(strcmp(str9, "C:") == 0);
assert(strcmp(str10, "C:\\Games\\AGS\\MyNewGame") == 0);
assert(strcmp(str11, "") == 0);
}
// Test making new string
{
String s1 = "we have some string here";
assert(strcmp(s1, "we have some string here") == 0);
s1.Empty();
assert(strcmp(s1, "") == 0);
s1.FillString('z', 10);
assert(strcmp(s1, "zzzzzzzzzz") == 0);
s1.FillString('a', 0);
assert(strcmp(s1, "") == 0);
s1.Format("this %d is %9ld a %x formatted %0.2f string %s", 1, 2, 100, 22.55F, "abcd");
assert(strcmp(s1, "this 1 is 2 a 64 formatted 22.55 string abcd") == 0);
s1.SetString("some string");
assert(strcmp(s1, "some string") == 0);
s1.SetString("some string", 4);
assert(strcmp(s1, "some") == 0);
}
// Test Upper/Lower case
{
String s1 = "ThIs StRiNg Is TwIsTeD";
String s2 = s1;
String s3 = s1;
s2.MakeLower();
s3.MakeUpper();
assert(strcmp(s2, "this string is twisted") == 0);
assert(strcmp(s3, "THIS STRING IS TWISTED") == 0);
}
// Test Prepend
{
String s1 = "- a string to enlarge";
s1.Prepend("make it bigger ");
assert(strcmp(s1, "make it bigger - a string to enlarge") == 0);
s1.PrependChar('!');
assert(strcmp(s1, "!make it bigger - a string to enlarge") == 0);
s1.PrependChar(' ');
assert(strcmp(s1, " !make it bigger - a string to enlarge") == 0);
s1.Prepend("much much bigger!");
assert(strcmp(s1, "much much bigger! !make it bigger - a string to enlarge") == 0);
}
// Test ReplaceMid
{
String s1 = "we need to replace PRECISELY THIS PART in this string";
String s2 = s1;
String new_long = "WITH A NEW TAD LONGER SUBSTRING";
String new_short = "SMALL STRING";
s1.ReplaceMid(19, 19, new_long);
assert(strcmp(s1, "we need to replace WITH A NEW TAD LONGER SUBSTRING in this string") == 0);
s2.ReplaceMid(19, 19, new_short);
assert(strcmp(s2, "we need to replace SMALL STRING in this string") == 0);
String s3 = "insert new string here: ";
s3.ReplaceMid(s3.GetLength(), 0, "NEW STRING");
assert(strcmp(s3, "insert new string here: NEW STRING") == 0);
}
// Test SetAt
{
String s1 = "strimg wiyh typos";
s1.SetAt((size_t) - 1, 'a');
assert(strcmp(s1, "strimg wiyh typos") == 0);
s1.SetAt(100, 'a');
assert(strcmp(s1, "strimg wiyh typos") == 0);
s1.SetAt(1, 0);
assert(strcmp(s1, "strimg wiyh typos") == 0);
s1.SetAt(4, 'n');
s1.SetAt(9, 't');
assert(strcmp(s1, "string with typos") == 0);
}
// Test Trim
{
String str1 = "\t This string is quite long and should be cut a little bit\r\n ";
String str2 = str1;
String str3 = str1;
String str4 = str1;
String str5 = "There's nothing to trim here";
str1.TrimLeft();
str2.TrimRight();
str3.Trim();
str4.Trim('|');
str5.Trim();
assert(strcmp(str1, "This string is quite long and should be cut a little bit\r\n ") == 0);
assert(strcmp(str2, "\t This string is quite long and should be cut a little bit") == 0);
assert(strcmp(str3, "This string is quite long and should be cut a little bit") == 0);
assert(strcmp(str4, "\t This string is quite long and should be cut a little bit\r\n ") == 0);
assert(strcmp(str5, "There's nothing to trim here") == 0);
}
// Test Truncate
{
String str1 = "long truncateable string";
String str2 = str1;
String str3 = str1;
String str4 = str1;
String str5 = str1;
str1.TruncateToLeft(4);
str2.TruncateToRight(6);
str3.TruncateToMid(5, 12);
str4.TruncateToMid(5, 0);
str5.TruncateToMid(0);
assert(strcmp(str1, "long") == 0);
assert(strcmp(str2, "string") == 0);
assert(strcmp(str3, "truncateable") == 0);
assert(strcmp(str4, "") == 0);
assert(strcmp(str5, "long truncateable string") == 0);
}
// Test TruncateToSection
{
String str1 = "C:\\Games\\AGS\\MyNewGame";
String str2 = str1;
String str3 = str1;
String str4 = str1;
String str5 = str1;
String str6 = str1;
String str7 = str1;
String str8 = str1;
String str9 = str1;
String str10 = str1;
String str11 = str1;
String str12 = str1;
str1.TruncateToLeftSection('\\');
str2.TruncateToLeftSection('\\', false);
str3.TruncateToRightSection('\\');
str4.TruncateToRightSection('\\', false);
str5.TruncateToSection('\\', 1, 2);
str6.TruncateToSection('\\', 1, 2, false, false);
str7.TruncateToSection('|', 1, 3);
str8.TruncateToSection('\\', 0, 2);
str9.TruncateToSection('\\', 1, 3);
str10.TruncateToSection('\\', 3, 1);
str11.TruncateToSection('\\', 3, 3);
str12.TruncateToSection('\\', 3, 3, false, false);
assert(strcmp(str1, "C:") == 0);
assert(strcmp(str2, "C:\\") == 0);
assert(strcmp(str3, "MyNewGame") == 0);
assert(strcmp(str4, "\\MyNewGame") == 0);
assert(strcmp(str5, "Games\\AGS") == 0);
assert(strcmp(str6, "\\Games\\AGS\\") == 0);
assert(strcmp(str7, "") == 0);
assert(strcmp(str8, "C:\\Games\\AGS") == 0);
assert(strcmp(str9, "Games\\AGS\\MyNewGame") == 0);
assert(strcmp(str10, "") == 0);
assert(strcmp(str11, "MyNewGame") == 0);
assert(strcmp(str12, "\\MyNewGame") == 0);
}
// Test Split
{
String str1 = "C:\\Games\\AGS\\MyNewGame\\";
std::vector<String> result = str1.Split('\\');
assert(result.size() == 5);
assert(strcmp(result[0], "C:") == 0);
assert(strcmp(result[1], "Games") == 0);
assert(strcmp(result[2], "AGS") == 0);
assert(strcmp(result[3], "MyNewGame") == 0);
assert(strcmp(result[4], "") == 0);
String str2 = "test,,,test";
result = str2.Split(',');
assert(result.size() == 4);
assert(strcmp(result[0], "test") == 0);
assert(strcmp(result[1], "") == 0);
assert(strcmp(result[2], "") == 0);
assert(strcmp(result[3], "test") == 0);
String str3 = ",,test,,";
result = str3.Split(',');
assert(result.size() == 5);
assert(strcmp(result[0], "") == 0);
assert(strcmp(result[1], "") == 0);
assert(strcmp(result[2], "test") == 0);
assert(strcmp(result[3], "") == 0);
assert(strcmp(result[4], "") == 0);
}
// Test Wrap
#if defined(AGS_PLATFORM_TEST) && AGS_PLATFORM_TEST
{
const char *cstr = "This is a string literal";
String str1 = String::Wrapper(cstr);
String str2 = str1;
assert(str1.GetCStr() == cstr);
assert(str2.GetCStr() == cstr);
assert(str1.GetRefCount() == 0);
assert(str2.GetRefCount() == 0);
str2.SetAt(0, 'A');
assert(str2.GetCStr() != cstr);
assert(str2.GetRefCount() == 1);
}
#endif
}
} // namespace AGS3

View File

@@ -0,0 +1,118 @@
/* 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/core/platform.h"
//#include "ags/shared/debugging/assert.h"
// File not present??
#include "common/scummsys.h"
#include "ags/shared/util/version.h"
namespace AGS3 {
using AGS::Shared::Version;
void Test_Version() {
// Old version format
Version test_ver1 = Version("2.06.101");
Version test_ver2 = Version("2.56.654");
Version test_ver3 = Version("2.7.722");
Version test_ver4 = Version("2.72.872NMP");
Version test_ver5 = Version("3.2.0");
Version test_ver6 = Version("3.21.1115");
Version test_ver7 = Version("3.21.1115NMP");
// New version format
Version test_ver8 = Version("3.3.0.1130");
Version test_ver9 = Version("3.3.0.1130 BETA");
assert(test_ver1.Major == 2);
assert(test_ver1.Minor == 0);
assert(test_ver1.Release == 6);
assert(test_ver1.Revision == 101);
assert(strcmp(test_ver1.LongString.GetCStr(), "2.0.6.101") == 0);
assert(strcmp(test_ver1.BackwardCompatibleString.GetCStr(), "2.06.101") == 0);
assert(strcmp(test_ver1.ShortString.GetCStr(), "2.0") == 0);
assert(test_ver2.Major == 2);
assert(test_ver2.Minor == 5);
assert(test_ver2.Release == 6);
assert(test_ver2.Revision == 654);
assert(strcmp(test_ver2.LongString.GetCStr(), "2.5.6.654") == 0);
assert(strcmp(test_ver2.BackwardCompatibleString.GetCStr(), "2.56.654") == 0);
assert(strcmp(test_ver2.ShortString.GetCStr(), "2.5") == 0);
assert(test_ver3.Major == 2);
assert(test_ver3.Minor == 7);
assert(test_ver3.Release == 0);
assert(test_ver3.Revision == 722);
assert(strcmp(test_ver3.LongString.GetCStr(), "2.7.0.722") == 0);
assert(strcmp(test_ver3.BackwardCompatibleString.GetCStr(), "2.70.722") == 0);
assert(strcmp(test_ver3.ShortString.GetCStr(), "2.7") == 0);
assert(test_ver4.Major == 2);
assert(test_ver4.Minor == 7);
assert(test_ver4.Release == 2);
assert(test_ver4.Revision == 872);
assert(strcmp(test_ver4.LongString.GetCStr(), "2.7.2.872 NMP") == 0);
assert(strcmp(test_ver4.BackwardCompatibleString.GetCStr(), "2.72.872NMP") == 0);
assert(strcmp(test_ver4.ShortString.GetCStr(), "2.7") == 0);
assert(test_ver5.Major == 3);
assert(test_ver5.Minor == 2);
assert(test_ver5.Release == 0);
assert(test_ver5.Revision == 0);
assert(strcmp(test_ver5.LongString.GetCStr(), "3.2.0.0") == 0);
assert(strcmp(test_ver5.BackwardCompatibleString.GetCStr(), "3.20.0") == 0);
assert(strcmp(test_ver5.ShortString.GetCStr(), "3.2") == 0);
assert(test_ver6.Major == 3);
assert(test_ver6.Minor == 2);
assert(test_ver6.Release == 1);
assert(test_ver6.Revision == 1115);
assert(strcmp(test_ver6.LongString.GetCStr(), "3.2.1.1115") == 0);
assert(strcmp(test_ver6.BackwardCompatibleString.GetCStr(), "3.21.1115") == 0);
assert(strcmp(test_ver6.ShortString.GetCStr(), "3.2") == 0);
assert(test_ver7.Major == 3);
assert(test_ver7.Minor == 2);
assert(test_ver7.Release == 1);
assert(test_ver7.Revision == 1115);
assert(strcmp(test_ver7.LongString.GetCStr(), "3.2.1.1115 NMP") == 0);
assert(strcmp(test_ver7.BackwardCompatibleString.GetCStr(), "3.21.1115NMP") == 0);
assert(strcmp(test_ver7.ShortString.GetCStr(), "3.2") == 0);
assert(test_ver8.Major == 3);
assert(test_ver8.Minor == 3);
assert(test_ver8.Release == 0);
assert(test_ver8.Revision == 1130);
assert(strcmp(test_ver8.LongString.GetCStr(), "3.3.0.1130") == 0);
assert(strcmp(test_ver8.BackwardCompatibleString.GetCStr(), "3.30.1130") == 0);
assert(strcmp(test_ver8.ShortString.GetCStr(), "3.3") == 0);
assert(test_ver9.Major == 3);
assert(test_ver9.Minor == 3);
assert(test_ver9.Release == 0);
assert(test_ver9.Revision == 1130);
assert(strcmp(test_ver9.LongString.GetCStr(), "3.3.0.1130 BETA") == 0);
assert(strcmp(test_ver9.BackwardCompatibleString.GetCStr(), "3.30.1130BETA") == 0);
assert(strcmp(test_ver9.ShortString.GetCStr(), "3.3") == 0);
}
} // namespace AGS3