mirror of
https://github.com/thunderbrewhq/squall.git
synced 2026-05-04 22:33:51 +00:00
feat: sync with Whoa implementation
This commit is contained in:
parent
12ab8f7721
commit
6928bf3f0c
46 changed files with 2980 additions and 441 deletions
2
lib/bc
2
lib/bc
|
|
@ -1 +1 @@
|
|||
Subproject commit 367b8149f36a1e4c2aad066e0cf9cd1e07ae7d88
|
||||
Subproject commit b9dd205765782a44afc03740f3047ab2be5f1c4f
|
||||
|
|
@ -1,17 +1,18 @@
|
|||
#include "storm/Big.hpp"
|
||||
#include "storm/big/BigData.hpp"
|
||||
#include "storm/big/Ops.hpp"
|
||||
#include <bc/Memory.hpp>
|
||||
#include <cstring>
|
||||
|
||||
void SBigAdd(BigData* a, BigData* b, BigData* c) {
|
||||
void STORMAPI SBigAdd(BigData* a, BigData* b, BigData* c) {
|
||||
Add(a->Primary(), b->Primary(), c->Primary());
|
||||
}
|
||||
|
||||
void SBigAnd(BigData* a, BigData* b, BigData* c) {
|
||||
void STORMAPI SBigAnd(BigData* a, BigData* b, BigData* c) {
|
||||
And(a->Primary(), b->Primary(), c->Primary());
|
||||
}
|
||||
|
||||
void SBigBitLen(BigData* num, uint32_t* len) {
|
||||
void STORMAPI SBigBitLen(BigData* num, uint32_t* len) {
|
||||
auto& buffer = num->Primary();
|
||||
buffer.Trim();
|
||||
|
||||
|
|
@ -28,24 +29,23 @@ void SBigBitLen(BigData* num, uint32_t* len) {
|
|||
*len = (index * 32) + bitIndex + 1;
|
||||
}
|
||||
|
||||
int32_t SBigCompare(BigData* a, BigData* b) {
|
||||
int32_t STORMAPI SBigCompare(BigData* a, BigData* b) {
|
||||
return Compare(a->Primary(), b->Primary());
|
||||
}
|
||||
|
||||
void SBigCopy(BigData* a, BigData* b) {
|
||||
void STORMAPI SBigCopy(BigData* a, BigData* b) {
|
||||
a->m_primary = b->m_primary;
|
||||
}
|
||||
|
||||
void SBigDec(BigData* a, BigData* b) {
|
||||
void STORMAPI SBigDec(BigData* a, BigData* b) {
|
||||
Sub(a->m_primary, b->m_primary, 1);
|
||||
}
|
||||
|
||||
void SBigDel(BigData* num) {
|
||||
num->~BigData();
|
||||
SMemFree(num);
|
||||
void STORMAPI SBigDel(BigData* num) {
|
||||
delete num;
|
||||
}
|
||||
|
||||
void SBigDiv(BigData* a, BigData* b, BigData* c) {
|
||||
void STORMAPI SBigDiv(BigData* a, BigData* b, BigData* c) {
|
||||
uint32_t allocCount = 0;
|
||||
BigBuffer& buf = a->Stack().Alloc(&allocCount);
|
||||
|
||||
|
|
@ -54,39 +54,39 @@ void SBigDiv(BigData* a, BigData* b, BigData* c) {
|
|||
a->Stack().Free(allocCount);
|
||||
}
|
||||
|
||||
void SBigFromBinary(BigData* num, const void* data, uint32_t bytes) {
|
||||
void STORMAPI SBigFromBinary(BigData* num, const void* data, uint32_t bytes) {
|
||||
FromBinary(num->Primary(), data, bytes);
|
||||
}
|
||||
|
||||
void SBigFromStr(BigData* num, const char *str) {
|
||||
void STORMAPI SBigFromStr(BigData* num, const char *str) {
|
||||
FromStr(num->Primary(), str);
|
||||
}
|
||||
|
||||
void SBigFromUnsigned(BigData* num, uint32_t val) {
|
||||
void STORMAPI SBigFromUnsigned(BigData* num, uint32_t val) {
|
||||
FromUnsigned(num->Primary(), val);
|
||||
}
|
||||
|
||||
void SBigInc(BigData* a, BigData* b) {
|
||||
void STORMAPI SBigInc(BigData* a, BigData* b) {
|
||||
Add(a->Primary(), b->Primary(), 1);
|
||||
}
|
||||
|
||||
int32_t SBigIsEven(BigData* a) {
|
||||
int32_t STORMAPI SBigIsEven(BigData* a) {
|
||||
return IsEven(a->Primary());
|
||||
}
|
||||
|
||||
int32_t SBigIsOdd(BigData* a) {
|
||||
int32_t STORMAPI SBigIsOdd(BigData* a) {
|
||||
return IsOdd(a->Primary());
|
||||
}
|
||||
|
||||
int32_t SBigIsOne(BigData* a) {
|
||||
int32_t STORMAPI SBigIsOne(BigData* a) {
|
||||
return IsOne(a->Primary());
|
||||
}
|
||||
|
||||
int32_t SBigIsZero(BigData* a) {
|
||||
int32_t STORMAPI SBigIsZero(BigData* a) {
|
||||
return IsZero(a->Primary());
|
||||
}
|
||||
|
||||
void SBigMod(BigData* a, BigData* b, BigData* c) {
|
||||
void STORMAPI SBigMod(BigData* a, BigData* b, BigData* c) {
|
||||
uint32_t allocCount = 0;
|
||||
auto& scratch = a->Stack().Alloc(&allocCount);
|
||||
|
||||
|
|
@ -95,44 +95,43 @@ void SBigMod(BigData* a, BigData* b, BigData* c) {
|
|||
a->Stack().Free(allocCount);
|
||||
}
|
||||
|
||||
void SBigMul(BigData* a, BigData* b, BigData* c) {
|
||||
void STORMAPI SBigMul(BigData* a, BigData* b, BigData* c) {
|
||||
Mul(a->Primary(), b->Primary(), c->Primary(), a->Stack());
|
||||
}
|
||||
|
||||
void SBigNew(BigData** num) {
|
||||
auto m = SMemAlloc(sizeof(BigData), __FILE__, __LINE__, 0x0);
|
||||
*num = new (m) BigData();
|
||||
void STORMAPI SBigNew(BigData** num) {
|
||||
*num = STORM_NEW(BigData);
|
||||
}
|
||||
|
||||
void SBigNot(BigData* a, BigData* b) {
|
||||
void STORMAPI SBigNot(BigData* a, BigData* b) {
|
||||
Not(a->Primary(), b->Primary());
|
||||
}
|
||||
|
||||
void SBigOr(BigData* a, BigData* b, BigData* c) {
|
||||
void STORMAPI SBigOr(BigData* a, BigData* b, BigData* c) {
|
||||
Or(a->Primary(), b->Primary(), c->Primary());
|
||||
}
|
||||
|
||||
void SBigPowMod(BigData* a, BigData* b, BigData* c, BigData* d) {
|
||||
void STORMAPI SBigPowMod(BigData* a, BigData* b, BigData* c, BigData* d) {
|
||||
PowMod(a->Primary(), b->Primary(), c->Primary(), d->Primary(), a->Stack());
|
||||
}
|
||||
|
||||
void SBigShl(BigData* a, BigData* b, uint32_t shift) {
|
||||
void STORMAPI SBigShl(BigData* a, BigData* b, uint32_t shift) {
|
||||
Shl(a->Primary(), b->Primary(), shift);
|
||||
}
|
||||
|
||||
void SBigShr(BigData* a, BigData* b, uint32_t shift) {
|
||||
void STORMAPI SBigShr(BigData* a, BigData* b, uint32_t shift) {
|
||||
Shr(a->Primary(), b->Primary(), shift);
|
||||
}
|
||||
|
||||
void SBigSquare(BigData* a, BigData* b) {
|
||||
void STORMAPI SBigSquare(BigData* a, BigData* b) {
|
||||
Square(a->Primary(), b->Primary(), a->Stack());
|
||||
}
|
||||
|
||||
void SBigSub(BigData* a, BigData* b, BigData* c) {
|
||||
void STORMAPI SBigSub(BigData* a, BigData* b, BigData* c) {
|
||||
Sub(a->Primary(), b->Primary(), c->Primary());
|
||||
}
|
||||
|
||||
void SBigToBinaryBuffer(BigData* num, uint8_t* data, uint32_t maxBytes, uint32_t* bytes) {
|
||||
void STORMAPI SBigToBinaryBuffer(BigData* num, uint8_t* data, uint32_t maxBytes, uint32_t* bytes) {
|
||||
auto& output = num->Output();
|
||||
ToBinary(output, num->Primary());
|
||||
|
||||
|
|
@ -144,6 +143,10 @@ void SBigToBinaryBuffer(BigData* num, uint8_t* data, uint32_t maxBytes, uint32_t
|
|||
}
|
||||
}
|
||||
|
||||
void SBigXor(BigData* a, BigData* b, BigData* c) {
|
||||
void STORMAPI SBigToUnsigned(BigData* num, uint32_t* val) {
|
||||
ToUnsigned(val, num->Primary());
|
||||
}
|
||||
|
||||
void STORMAPI SBigXor(BigData* a, BigData* b, BigData* c) {
|
||||
Xor(a->Primary(), b->Primary(), c->Primary());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,63 +1,66 @@
|
|||
#ifndef STORM_BIG_HPP
|
||||
#define STORM_BIG_HPP
|
||||
|
||||
#include "storm/big/BigData.hpp"
|
||||
#include <cstdint>
|
||||
#include "Core.hpp"
|
||||
|
||||
void SBigAdd(BigData* a, BigData* b, BigData* c);
|
||||
class BigData;
|
||||
|
||||
void SBigAnd(BigData* a, BigData* b, BigData* c);
|
||||
void STORMAPI SBigAdd(BigData* a, BigData* b, BigData* c);
|
||||
|
||||
void SBigBitLen(BigData* num, uint32_t* len);
|
||||
void STORMAPI SBigAnd(BigData* a, BigData* b, BigData* c);
|
||||
|
||||
int32_t SBigCompare(BigData* a, BigData* b);
|
||||
void STORMAPI SBigBitLen(BigData* num, uint32_t* len);
|
||||
|
||||
void SBigCopy(BigData* a, BigData* b);
|
||||
int32_t STORMAPI SBigCompare(BigData* a, BigData* b);
|
||||
|
||||
void SBigDec(BigData* a, BigData* b);
|
||||
void STORMAPI SBigCopy(BigData* a, BigData* b);
|
||||
|
||||
void SBigDel(BigData* num);
|
||||
void STORMAPI SBigDec(BigData* a, BigData* b);
|
||||
|
||||
void SBigDiv(BigData* a, BigData* b, BigData* c);
|
||||
void STORMAPI SBigDel(BigData* num);
|
||||
|
||||
void SBigFromBinary(BigData* num, const void* data, uint32_t bytes);
|
||||
void STORMAPI SBigDiv(BigData* a, BigData* b, BigData* c);
|
||||
|
||||
void SBigFromStr(BigData* num, const char* str);
|
||||
void STORMAPI SBigFromBinary(BigData* num, const void* data, uint32_t bytes);
|
||||
|
||||
void SBigFromUnsigned(BigData* num, uint32_t val);
|
||||
void STORMAPI SBigFromStr(BigData* num, const char* str);
|
||||
|
||||
void SBigInc(BigData* a, BigData* b);
|
||||
void STORMAPI SBigFromUnsigned(BigData* num, uint32_t val);
|
||||
|
||||
int32_t SBigIsEven(BigData* a);
|
||||
void STORMAPI SBigInc(BigData* a, BigData* b);
|
||||
|
||||
int32_t SBigIsOdd(BigData* a);
|
||||
int32_t STORMAPI SBigIsEven(BigData* a);
|
||||
|
||||
int32_t SBigIsOne(BigData* a);
|
||||
int32_t STORMAPI SBigIsOdd(BigData* a);
|
||||
|
||||
int32_t SBigIsZero(BigData* a);
|
||||
int32_t STORMAPI SBigIsOne(BigData* a);
|
||||
|
||||
void SBigMod(BigData* a, BigData* b, BigData* c);
|
||||
int32_t STORMAPI SBigIsZero(BigData* a);
|
||||
|
||||
void SBigMul(BigData* a, BigData* b, BigData* c);
|
||||
void STORMAPI SBigMod(BigData* a, BigData* b, BigData* c);
|
||||
|
||||
void SBigNew(BigData** num);
|
||||
void STORMAPI SBigMul(BigData* a, BigData* b, BigData* c);
|
||||
|
||||
void SBigNot(BigData* a, BigData* b);
|
||||
void STORMAPI SBigNew(BigData** num);
|
||||
|
||||
void SBigOr(BigData* a, BigData* b, BigData* c);
|
||||
void STORMAPI SBigNot(BigData* a, BigData* b);
|
||||
|
||||
void SBigPowMod(BigData* a, BigData* b, BigData* c, BigData* d);
|
||||
void STORMAPI SBigOr(BigData* a, BigData* b, BigData* c);
|
||||
|
||||
void SBigShl(BigData* a, BigData* b, uint32_t shift);
|
||||
void STORMAPI SBigPowMod(BigData* a, BigData* b, BigData* c, BigData* d);
|
||||
|
||||
void SBigShr(BigData* a, BigData* b, uint32_t shift);
|
||||
void STORMAPI SBigShl(BigData* a, BigData* b, uint32_t shift);
|
||||
|
||||
void SBigSquare(BigData* a, BigData* b);
|
||||
void STORMAPI SBigShr(BigData* a, BigData* b, uint32_t shift);
|
||||
|
||||
void SBigSub(BigData* a, BigData* b, BigData* c);
|
||||
void STORMAPI SBigSquare(BigData* a, BigData* b);
|
||||
|
||||
void SBigToBinaryBuffer(BigData* num, uint8_t* data, uint32_t maxBytes, uint32_t* bytes);
|
||||
void STORMAPI SBigSub(BigData* a, BigData* b, BigData* c);
|
||||
|
||||
void SBigXor(BigData* a, BigData* b, BigData* c);
|
||||
void STORMAPI SBigToBinaryBuffer(BigData* num, uint8_t* data, uint32_t maxBytes, uint32_t* bytes);
|
||||
|
||||
void STORMAPI SBigXor(BigData* a, BigData* b, BigData* c);
|
||||
|
||||
void STORMAPI SBigToUnsigned(BigData* num, uint32_t* val);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ file(GLOB STORM_SOURCES
|
|||
"crypto/*.cpp"
|
||||
"error/*.cpp"
|
||||
"hash/*.cpp"
|
||||
"option*/*.cpp"
|
||||
"option/*.cpp"
|
||||
"queue/*.cpp"
|
||||
"string/*.cpp"
|
||||
"thread/*.cpp"
|
||||
|
|
|
|||
31
storm/Core.cpp
Normal file
31
storm/Core.cpp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include "Core.hpp"
|
||||
#include "Event.hpp"
|
||||
#include "Region.hpp"
|
||||
#include "String.hpp"
|
||||
#include "Transparency.hpp"
|
||||
|
||||
int32_t STORMAPI StormDestroy() {
|
||||
// Combined list of all destroy calls found in every game (as documentation)
|
||||
|
||||
// SErrSetBlizzardErrorFunction(nullptr); // SC 1.17
|
||||
// SDlgDestroy(); // SC 1.17
|
||||
// SGdiDestroy(); // SC 1.17
|
||||
// SVidDestroy(); // SC 1.17
|
||||
// SDrawDestroy(); // SC 1.17
|
||||
SRgnDestroy(); // WoW 3.3.5 (win), SC 1.17
|
||||
// SMsgDestroy(); // WoW 3.3.5 (win), SC 1.17
|
||||
// SNetDestroy(); // SC 1.17
|
||||
SEvtDestroy(); // WoW 3.3.5 (win)
|
||||
// SBltDestroy(); // SC 1.17
|
||||
// SCodeDestroy(); // SC 1.17
|
||||
// SCmdDestroy(); // WoW 3.3.5 (win+mac), SC 1.17
|
||||
// SFileDestroy(); // WoW 3.3.5 (mac)?, SC 1.17
|
||||
// SFile::Destroy(); // WoW 0.5.3 (win)?
|
||||
// SCompDestroy(); // WoW 3.3.5 (win)?
|
||||
SStrDestroy(); // WoW 3.3.5 (mac), SC 1.17
|
||||
// SRegDestroy(); // WoW 3.3.5 (mac)
|
||||
// SErrDestroy(); // WoW 3.3.5 (mac)
|
||||
// SLogDestroy(); // WoW 3.3.5 (mac)
|
||||
STransDestroy(); // SC 1.17
|
||||
return 1;
|
||||
}
|
||||
23
storm/Core.hpp
Normal file
23
storm/Core.hpp
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef STORM_CORE_HPP
|
||||
#define STORM_CORE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#ifndef STORMAPI
|
||||
#if defined(_MSC_VER)
|
||||
#define STORMAPI __stdcall
|
||||
#define STORMCDECL __cdecl
|
||||
#else
|
||||
#define STORMAPI
|
||||
#define STORMCDECL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(WHOA_SYSTEM_WIN)
|
||||
typedef void* HANDLE;
|
||||
typedef void* LPOVERLAPPED;
|
||||
#endif
|
||||
|
||||
int32_t STORMAPI StormDestroy();
|
||||
|
||||
#endif
|
||||
420
storm/Event.cpp
Normal file
420
storm/Event.cpp
Normal file
|
|
@ -0,0 +1,420 @@
|
|||
#include "Event.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "list/TSList.hpp"
|
||||
#include "thread/CCritSect.hpp"
|
||||
#include "Atomic.hpp"
|
||||
#include "Error.hpp"
|
||||
#include <bc/Memory.hpp>
|
||||
|
||||
struct BREAKCMD : public TSLinkedNode<BREAKCMD> {
|
||||
void* data;
|
||||
};
|
||||
|
||||
static CCritSect s_critsect;
|
||||
static TSList<BREAKCMD, TSGetLink<BREAKCMD>> s_breakcmdlist;
|
||||
static int32_t s_modified;
|
||||
static ATOMIC32 s_dispatchesinprogress;
|
||||
|
||||
struct _IDHASHENTRY {
|
||||
uint32_t id;
|
||||
uint32_t sequence;
|
||||
SEVTHANDLER handler;
|
||||
_IDHASHENTRY* next;
|
||||
};
|
||||
|
||||
struct _IDHASHTABLE {
|
||||
_IDHASHENTRY** data;
|
||||
uint32_t size;
|
||||
uint32_t used;
|
||||
_IDHASHTABLE* next;
|
||||
};
|
||||
|
||||
struct _TYPEHASHENTRY {
|
||||
uint32_t type;
|
||||
uint32_t subtype;
|
||||
uint32_t sequence;
|
||||
_IDHASHTABLE* idhashtable;
|
||||
_TYPEHASHENTRY* next;
|
||||
};
|
||||
|
||||
static _TYPEHASHENTRY **s_typehashtable;
|
||||
static uint32_t s_typehashtablesize;
|
||||
static uint32_t s_typehashtableused;
|
||||
|
||||
// Fake function to make tests not bleed into each other
|
||||
void SEvtCleanExtraDataForTests() {
|
||||
s_breakcmdlist.Clear();
|
||||
}
|
||||
|
||||
void DeleteIdHashTable(_IDHASHTABLE* pTable) {
|
||||
for (uint32_t i = 0; i < pTable->size; i++) {
|
||||
for (_IDHASHENTRY* pEntry = pTable->data[i]; pEntry; pEntry = pTable->data[i]) {
|
||||
pTable->data[i] = pEntry->next;
|
||||
delete pEntry;
|
||||
}
|
||||
}
|
||||
STORM_FREE(pTable->data);
|
||||
delete pTable;
|
||||
}
|
||||
|
||||
_TYPEHASHENTRY* FindTypeHashEntry(uint32_t type, uint32_t subtype) {
|
||||
if (!s_typehashtable || s_typehashtablesize == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (_TYPEHASHENTRY* pEntry = s_typehashtable[(s_typehashtablesize - 1) & (subtype ^ type)]; pEntry; pEntry = pEntry->next) {
|
||||
if (pEntry->type == type && pEntry->subtype == subtype) {
|
||||
return pEntry;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t ComputeNewTableSize(uint32_t size) {
|
||||
uint32_t result = 1;
|
||||
while (result <= size * 2 + 2) {
|
||||
result *= 2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void CopyIdHashTable(_IDHASHTABLE *dest, _IDHASHTABLE *source) {
|
||||
dest->size = source->size;
|
||||
dest->used = source->used;
|
||||
dest->data = (_IDHASHENTRY**)STORM_ALLOC(sizeof(_IDHASHENTRY*) * dest->size);
|
||||
|
||||
for (uint32_t i = 0; i < source->size; i++) {
|
||||
_IDHASHENTRY* pSourceData = source->data[i];
|
||||
_IDHASHENTRY** ppDestData = &dest->data[i];
|
||||
for (; pSourceData; pSourceData = pSourceData->next) {
|
||||
_IDHASHENTRY* pNewEntry = STORM_NEW(_IDHASHENTRY);
|
||||
|
||||
*ppDestData = pNewEntry;
|
||||
*pNewEntry = *pSourceData;
|
||||
ppDestData = &(*ppDestData)->next;
|
||||
}
|
||||
*ppDestData = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t STORMAPI SEvtBreakHandlerChain(void* data) {
|
||||
s_critsect.Enter();
|
||||
s_breakcmdlist.NewNode(2, 0, 0)->data = data;
|
||||
s_critsect.Leave();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t STORMAPI SEvtDestroy() {
|
||||
s_critsect.Enter();
|
||||
|
||||
for (uint32_t i = 0; i < s_typehashtablesize; i++) {
|
||||
for (_TYPEHASHENTRY* pTypeEntry = s_typehashtable[i]; pTypeEntry; pTypeEntry = s_typehashtable[i]) {
|
||||
for (_IDHASHTABLE* pTable = pTypeEntry->idhashtable; pTable; pTable = pTypeEntry->idhashtable) {
|
||||
pTypeEntry->idhashtable = pTable->next;
|
||||
DeleteIdHashTable(pTable);
|
||||
}
|
||||
s_typehashtable[i] = pTypeEntry->next;
|
||||
delete pTypeEntry;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_typehashtable) {
|
||||
delete s_typehashtable;
|
||||
}
|
||||
s_typehashtable = nullptr;
|
||||
s_typehashtablesize = 0;
|
||||
s_typehashtableused = 0;
|
||||
|
||||
s_modified = 1;
|
||||
|
||||
s_critsect.Leave();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t STORMAPI SEvtDispatch(uint32_t type, uint32_t subtype, uint32_t id, void* data) {
|
||||
SInterlockedIncrement(&s_dispatchesinprogress);
|
||||
|
||||
int32_t success = 0;
|
||||
uint32_t currsequence = -1;
|
||||
_IDHASHENTRY *currptr = nullptr;
|
||||
|
||||
do {
|
||||
s_critsect.Enter();
|
||||
|
||||
bool breakcmd = false;
|
||||
for (BREAKCMD* curr = s_breakcmdlist.Head(); reinterpret_cast<intptr_t>(curr) > 0; curr = s_breakcmdlist.RawNext(curr)) {
|
||||
if (curr->data == data) {
|
||||
breakcmd = true;
|
||||
s_breakcmdlist.DeleteNode(curr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (breakcmd) {
|
||||
s_critsect.Leave();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!currptr || s_modified) {
|
||||
currptr = nullptr;
|
||||
auto typeentry = FindTypeHashEntry(type, subtype);
|
||||
if (typeentry) {
|
||||
_IDHASHTABLE* idhash = typeentry->idhashtable;
|
||||
if (idhash->data && idhash->size != 0) {
|
||||
for (currptr = idhash->data[id & (idhash->size - 1)]; currptr; currptr = currptr->next) {
|
||||
if (currptr->id == id && currptr->sequence < currsequence) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_dispatchesinprogress == 1) {
|
||||
s_modified = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SEVTHANDLER handler = nullptr;
|
||||
|
||||
if (currptr) {
|
||||
handler = currptr->handler;
|
||||
currsequence = currptr->sequence;
|
||||
do {
|
||||
currptr = currptr->next;
|
||||
} while (currptr && currptr->id != id);
|
||||
}
|
||||
|
||||
s_critsect.Leave();
|
||||
|
||||
if (handler) {
|
||||
success = 1;
|
||||
handler(data);
|
||||
}
|
||||
} while(currptr);
|
||||
|
||||
SInterlockedDecrement(&s_dispatchesinprogress);
|
||||
|
||||
if (s_breakcmdlist.Head()) {
|
||||
s_critsect.Enter();
|
||||
|
||||
for (BREAKCMD* curr = s_breakcmdlist.Head(); reinterpret_cast<intptr_t>(curr) > 0;) {
|
||||
if (curr->data == data) {
|
||||
curr = s_breakcmdlist.DeleteNode(curr);
|
||||
}
|
||||
else {
|
||||
curr = s_breakcmdlist.RawNext(curr);
|
||||
}
|
||||
}
|
||||
|
||||
s_critsect.Leave();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
int32_t STORMAPI SEvtPopState(uint32_t type, uint32_t subtype) {
|
||||
int32_t success = 0;
|
||||
s_critsect.Enter();
|
||||
|
||||
_TYPEHASHENTRY* typeentry = FindTypeHashEntry(type, subtype);
|
||||
if (typeentry) {
|
||||
_IDHASHTABLE *next = typeentry->idhashtable->next;
|
||||
if (next) {
|
||||
DeleteIdHashTable(typeentry->idhashtable);
|
||||
typeentry->idhashtable = next;
|
||||
}
|
||||
else {
|
||||
// This WILL hang if called without recursive CCritSect.
|
||||
// Provide a hack since it never gets called in WoW anyway.
|
||||
// It also doesn't get called by SC for that matter. Nothing calls it. Classic.
|
||||
#if !defined(WHOA_STORM_C_CRIT_SECT_RECURSIVE)
|
||||
s_critsect.Leave();
|
||||
success = SEvtUnregisterType(type, subtype);
|
||||
s_critsect.Enter();
|
||||
#else
|
||||
success = SEvtUnregisterType(type, subtype);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
s_modified = 1;
|
||||
s_critsect.Leave();
|
||||
return success;
|
||||
}
|
||||
|
||||
int32_t STORMAPI SEvtPushState(uint32_t type, uint32_t subtype) {
|
||||
int32_t success = 0;
|
||||
s_critsect.Enter();
|
||||
|
||||
_TYPEHASHENTRY* pTypeHash = FindTypeHashEntry(type, subtype);
|
||||
if (pTypeHash) {
|
||||
_IDHASHTABLE* pNewTable = STORM_NEW(_IDHASHTABLE);
|
||||
|
||||
CopyIdHashTable(pNewTable, pTypeHash->idhashtable);
|
||||
pNewTable->next = pTypeHash->idhashtable;
|
||||
pTypeHash->idhashtable = pNewTable;
|
||||
|
||||
success = 1;
|
||||
s_modified = 1;
|
||||
}
|
||||
|
||||
s_critsect.Leave();
|
||||
return success;
|
||||
}
|
||||
|
||||
int32_t STORMAPI SEvtRegisterHandler(uint32_t type, uint32_t subtype, uint32_t id, uint32_t flags, SEVTHANDLER handler) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(handler);
|
||||
STORM_VALIDATE(!flags);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
s_critsect.Enter();
|
||||
|
||||
_TYPEHASHENTRY* pTypeHash = FindTypeHashEntry(type, subtype);
|
||||
if (!pTypeHash) {
|
||||
if (s_typehashtableused >= s_typehashtablesize / 2) {
|
||||
uint32_t newsize = ComputeNewTableSize(s_typehashtableused);
|
||||
_TYPEHASHENTRY** pNewTable = static_cast<_TYPEHASHENTRY**>(STORM_ALLOC_ZERO(sizeof(_TYPEHASHENTRY*) * newsize));
|
||||
|
||||
if (s_typehashtable) {
|
||||
for (uint32_t i = 0; i < s_typehashtablesize; i++) {
|
||||
_TYPEHASHENTRY* pNext;
|
||||
for (_TYPEHASHENTRY* pTable = s_typehashtable[i]; pTable; pTable = pNext) {
|
||||
pNext = pTable->next;
|
||||
|
||||
uint32_t idx = (newsize - 1) & (pTable->type ^ pTable->subtype);
|
||||
pTable->next = pNewTable[idx];
|
||||
pNewTable[idx] = pTable;
|
||||
}
|
||||
}
|
||||
if (s_typehashtable) {
|
||||
STORM_FREE(s_typehashtable);
|
||||
}
|
||||
}
|
||||
s_typehashtable = pNewTable;
|
||||
s_typehashtablesize = newsize;
|
||||
}
|
||||
|
||||
uint32_t idx = (s_typehashtablesize - 1) & (type ^ subtype);
|
||||
|
||||
_TYPEHASHENTRY* pNewTypeHash = STORM_NEW_ZERO(_TYPEHASHENTRY);
|
||||
|
||||
pNewTypeHash->type = type;
|
||||
pNewTypeHash->subtype = subtype;
|
||||
pNewTypeHash->idhashtable = STORM_NEW_ZERO(_IDHASHTABLE);
|
||||
pNewTypeHash->next = s_typehashtable[idx];
|
||||
|
||||
s_typehashtable[idx] = pNewTypeHash;
|
||||
s_typehashtableused++;
|
||||
|
||||
pTypeHash = pNewTypeHash;
|
||||
}
|
||||
|
||||
if (pTypeHash->idhashtable->used >= pTypeHash->idhashtable->size / 2) {
|
||||
uint32_t newsize = ComputeNewTableSize(pTypeHash->idhashtable->size);
|
||||
_IDHASHENTRY** pNewTable = static_cast<_IDHASHENTRY**>(STORM_ALLOC_ZERO(sizeof(_IDHASHENTRY*) * newsize));
|
||||
_IDHASHENTRY*** pTempTable = static_cast<_IDHASHENTRY***>(STORM_ALLOC_ZERO(sizeof(_IDHASHENTRY*) * newsize));
|
||||
|
||||
for (uint32_t i = 0; i < newsize; i++) {
|
||||
pTempTable[i] = &pNewTable[i];
|
||||
}
|
||||
|
||||
if (pTypeHash->idhashtable->data && pTypeHash->idhashtable->size != 0) {
|
||||
for (uint32_t i = 0; i < pTypeHash->idhashtable->size; i++) {
|
||||
_IDHASHENTRY* pNext;
|
||||
for (_IDHASHENTRY* pEntry = pTypeHash->idhashtable->data[i]; pEntry; pEntry = pNext) {
|
||||
uint32_t idx = (newsize - 1) & pEntry->id;
|
||||
pNext = pEntry->next;
|
||||
pEntry->next = nullptr;
|
||||
|
||||
*pTempTable[idx] = pEntry;
|
||||
pTempTable[idx] = &pEntry->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STORM_FREE(pTempTable);
|
||||
if (pTypeHash->idhashtable->data) {
|
||||
STORM_FREE(pTypeHash->idhashtable->data);
|
||||
}
|
||||
pTypeHash->idhashtable->data = pNewTable;
|
||||
pTypeHash->idhashtable->size = newsize;
|
||||
}
|
||||
|
||||
uint32_t idx = (pTypeHash->idhashtable->size - 1) & id;
|
||||
_IDHASHENTRY* pNewIdHash = STORM_NEW_ZERO(_IDHASHENTRY);
|
||||
|
||||
pNewIdHash->id = id;
|
||||
pNewIdHash->sequence = ++pTypeHash->sequence;
|
||||
pNewIdHash->handler = handler;
|
||||
|
||||
pNewIdHash->next = pTypeHash->idhashtable->data[idx];
|
||||
pTypeHash->idhashtable->data[idx] = pNewIdHash;
|
||||
|
||||
pTypeHash->idhashtable->used++;
|
||||
|
||||
s_modified = 1;
|
||||
s_critsect.Leave();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t STORMAPI SEvtUnregisterHandler(uint32_t type, uint32_t subtype, uint32_t id, SEVTHANDLER handler) {
|
||||
int32_t success = 0;
|
||||
s_critsect.Enter();
|
||||
|
||||
_TYPEHASHENTRY* pTypeEntry = FindTypeHashEntry(type, subtype);
|
||||
if (pTypeEntry) {
|
||||
_IDHASHTABLE* pTable = pTypeEntry->idhashtable;
|
||||
if (pTable->data && pTable->size != 0) {
|
||||
_IDHASHENTRY** ppNextEntry = &pTable->data[id & (pTable->size - 1)];
|
||||
for (_IDHASHENTRY* pEntry = *ppNextEntry; pEntry; pEntry = *ppNextEntry) {
|
||||
if (pEntry->id == id && (!handler || pEntry->handler == handler)) {
|
||||
*ppNextEntry = pEntry->next;
|
||||
delete pEntry;
|
||||
|
||||
success = 1;
|
||||
s_modified = 1;
|
||||
pTable->used--;
|
||||
}
|
||||
else {
|
||||
ppNextEntry = &pEntry->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_critsect.Leave();
|
||||
return success;
|
||||
}
|
||||
|
||||
int32_t STORMAPI SEvtUnregisterType(uint32_t type, uint32_t subtype) {
|
||||
int32_t success = 0;
|
||||
s_critsect.Enter();
|
||||
|
||||
_TYPEHASHENTRY *pTypeEntry = FindTypeHashEntry(type, subtype);
|
||||
if (pTypeEntry) {
|
||||
for (auto pTable = pTypeEntry->idhashtable; pTable; pTable = pTypeEntry->idhashtable) {
|
||||
pTypeEntry->idhashtable = pTable->next;
|
||||
DeleteIdHashTable(pTable);
|
||||
}
|
||||
|
||||
uint32_t idx = (s_typehashtablesize - 1) & (subtype ^ type);
|
||||
_TYPEHASHENTRY** ppNextEntry = &s_typehashtable[idx];
|
||||
for (_TYPEHASHENTRY* pEntry = *ppNextEntry; pEntry; pEntry = *ppNextEntry) {
|
||||
if (pEntry == pTypeEntry) {
|
||||
*ppNextEntry = pEntry->next;
|
||||
delete pEntry;
|
||||
s_typehashtableused--;
|
||||
}
|
||||
else {
|
||||
ppNextEntry = &pEntry->next;
|
||||
}
|
||||
}
|
||||
|
||||
success = 1;
|
||||
s_modified = 1;
|
||||
}
|
||||
|
||||
s_critsect.Leave();
|
||||
return success;
|
||||
}
|
||||
25
storm/Event.hpp
Normal file
25
storm/Event.hpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef STORM_EVENT_HPP
|
||||
#define STORM_EVENT_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include "Core.hpp"
|
||||
|
||||
typedef void (STORMAPI* SEVTHANDLER)(void*);
|
||||
|
||||
int32_t STORMAPI SEvtBreakHandlerChain(void* data);
|
||||
|
||||
int32_t STORMAPI SEvtDestroy();
|
||||
|
||||
int32_t STORMAPI SEvtDispatch(uint32_t type, uint32_t subtype, uint32_t id, void* data);
|
||||
|
||||
int32_t STORMAPI SEvtPopState(uint32_t type, uint32_t subtype);
|
||||
|
||||
int32_t STORMAPI SEvtPushState(uint32_t type, uint32_t subtype);
|
||||
|
||||
int32_t STORMAPI SEvtRegisterHandler(uint32_t type, uint32_t subtype, uint32_t id, uint32_t flags, SEVTHANDLER handler);
|
||||
|
||||
int32_t STORMAPI SEvtUnregisterHandler(uint32_t type, uint32_t subtype, uint32_t id, SEVTHANDLER handler);
|
||||
|
||||
int32_t STORMAPI SEvtUnregisterType(uint32_t type, uint32_t subtype);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,24 +1,21 @@
|
|||
#ifndef STORM_HANDLE_HPP
|
||||
#define STORM_HANDLE_HPP
|
||||
|
||||
#if !defined(DECLARE_HANDLE)
|
||||
#define DECLARE_HANDLE(name) \
|
||||
struct name##__; \
|
||||
#define DECLARE_STORM_HANDLE(name) \
|
||||
struct name##__ { \
|
||||
int32_t unused; \
|
||||
}; \
|
||||
typedef struct name##__* name
|
||||
#endif
|
||||
|
||||
#if !defined(DECLARE_STRICT_HANDLE)
|
||||
#define DECLARE_STRICT_HANDLE(name) \
|
||||
#define DECLARE_STORM_STRICT_HANDLE(name) \
|
||||
typedef struct name##__ { \
|
||||
int unused; \
|
||||
}* name
|
||||
#endif
|
||||
|
||||
#if !defined(DECLARE_DERIVED_HANDLE)
|
||||
#define DECLARE_DERIVED_HANDLE(name, base) \
|
||||
typedef struct name##__ : public base##__ { \
|
||||
int unused; \
|
||||
}* name
|
||||
#endif
|
||||
#define DECLARE_STORM_CHILD_HANDLE(name, super) \
|
||||
struct name##__ : public super##__ { \
|
||||
int32_t unused; \
|
||||
}; \
|
||||
typedef struct name##__* name
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
#define STORM_LOG_FLAG_NO_FILE 2 // Don't use log file (use OutputDebugString or console only)
|
||||
#define STORM_LOG_FLAG_APPEND 4 // Don't truncate existing log file
|
||||
|
||||
DECLARE_STRICT_HANDLE(HSLOG);
|
||||
DECLARE_STRICT_HANDLE(HLOCKEDLOG);
|
||||
DECLARE_STORM_STRICT_HANDLE(HSLOG);
|
||||
DECLARE_STORM_STRICT_HANDLE(HLOCKEDLOG);
|
||||
|
||||
void SLogInitialize();
|
||||
int32_t SLogIsInitialized();
|
||||
|
|
|
|||
841
storm/Region.cpp
841
storm/Region.cpp
|
|
@ -3,10 +3,21 @@
|
|||
#include "storm/Error.hpp"
|
||||
#include "storm/Hash.hpp"
|
||||
#include "storm/Thread.hpp"
|
||||
|
||||
#include <limits>
|
||||
|
||||
static TSExportTableSyncReuse<RGN, HSRGN, HLOCKEDRGN, CCritSect> s_rgntable;
|
||||
|
||||
void DeleteCombinedRect(TSGrowableArray<RECTF>* combinedArray, uint32_t index);
|
||||
void DeleteRect(RECTF* rect);
|
||||
void DeleteSourceRect(TSGrowableArray<SOURCE>* sourceArray, uint32_t index);
|
||||
int32_t IsNullRect(const RECTF* rect);
|
||||
|
||||
void AddCombinedRect(TSGrowableArray<RECTF>* combinedArray, const RECTF* rect) {
|
||||
RECTF* newRect = combinedArray->New();
|
||||
*newRect = *rect;
|
||||
}
|
||||
|
||||
void AddSourceRect(TSGrowableArray<SOURCE>* sourceArray, const RECTF* rect, void* param, int32_t sequence, uint32_t flags) {
|
||||
auto source = sourceArray->New();
|
||||
|
||||
|
|
@ -17,10 +28,91 @@ void AddSourceRect(TSGrowableArray<SOURCE>* sourceArray, const RECTF* rect, void
|
|||
}
|
||||
|
||||
int32_t CheckForIntersection(const RECTF* sourceRect, const RECTF* targetRect) {
|
||||
#if defined(WHOA_RECT_USES_SCREEN_COORDINATES)
|
||||
return sourceRect->left < targetRect->right
|
||||
&& sourceRect->top < targetRect->bottom
|
||||
&& sourceRect->right > targetRect->left
|
||||
&& sourceRect->bottom > targetRect->top;
|
||||
#else
|
||||
return sourceRect->left < targetRect->right
|
||||
&& sourceRect->bottom < targetRect->top
|
||||
&& sourceRect->right > targetRect->left
|
||||
&& sourceRect->top > targetRect->bottom;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CombineRectangles(TSGrowableArray<RECTF>* combinedArray) {
|
||||
for (uint32_t i = 1; i < combinedArray->Count(); i++) {
|
||||
for (uint32_t j = 0; j < i; j++) {
|
||||
RECTF* rctA = &(*combinedArray)[i];
|
||||
RECTF* rctB = &(*combinedArray)[j];
|
||||
|
||||
if (rctA->left == rctB->left && rctA->right == rctB->right) {
|
||||
if (rctA->bottom == rctB->top || rctB->bottom == rctA->top) {
|
||||
#if defined(WHOA_RECT_USES_SCREEN_COORDINATES)
|
||||
rctA->top = std::min(rctB->top, rctA->top);
|
||||
rctA->bottom = std::max(rctB->bottom, rctA->bottom);
|
||||
#else
|
||||
rctA->bottom = std::min(rctB->bottom, rctA->bottom);
|
||||
rctA->top = std::max(rctB->top, rctA->top);
|
||||
#endif
|
||||
DeleteRect(rctB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rctA->left == rctB->right || rctB->left == rctA->right) {
|
||||
if (rctA->bottom == rctB->bottom && rctA->top == rctB->top) {
|
||||
rctA->left = std::min(rctB->left, rctA->left);
|
||||
rctA->right = std::max(rctB->right, rctA->right);
|
||||
DeleteRect(rctB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rctA->left == rctB->right || rctB->left == rctA->right) {
|
||||
RECTF newrect[5];
|
||||
|
||||
#if defined(WHOA_RECT_USES_SCREEN_COORDINATES)
|
||||
if (rctA->top < rctB->bottom && rctB->top < rctA->bottom) {
|
||||
newrect[0] = { rctA->left, rctA->top, rctA->right, rctB->top };
|
||||
newrect[1] = { rctB->left, rctB->top, rctB->right, rctA->top };
|
||||
newrect[2] = { rctA->left, rctB->bottom, rctA->right, rctA->bottom };
|
||||
newrect[3] = { rctB->left, rctA->bottom, rctB->right, rctB->bottom };
|
||||
|
||||
newrect[4] = {
|
||||
std::min(rctB->left, rctA->left),
|
||||
std::max(rctB->top, rctA->top),
|
||||
std::max(rctB->right, rctA->right),
|
||||
std::min(rctB->bottom, rctA->bottom)
|
||||
};
|
||||
#else
|
||||
if (rctA->bottom < rctB->top && rctB->bottom < rctA->top) {
|
||||
newrect[0] = { rctA->left, rctA->bottom, rctA->right, rctB->bottom };
|
||||
newrect[1] = { rctB->left, rctB->bottom, rctB->right, rctA->bottom };
|
||||
newrect[2] = { rctA->left, rctB->top, rctA->right, rctA->top };
|
||||
newrect[3] = { rctB->left, rctA->top, rctB->right, rctB->top };
|
||||
|
||||
newrect[4] = {
|
||||
std::min(rctB->left, rctA->left),
|
||||
std::max(rctB->bottom, rctA->bottom),
|
||||
std::max(rctB->right, rctA->right),
|
||||
std::min(rctB->top, rctA->top)
|
||||
};
|
||||
#endif
|
||||
|
||||
for (uint32_t k = 0; k < 5; k++) {
|
||||
if (!IsNullRect(&newrect[k])) {
|
||||
AddCombinedRect(combinedArray, &newrect[k]);
|
||||
}
|
||||
}
|
||||
DeleteCombinedRect(combinedArray, i);
|
||||
DeleteCombinedRect(combinedArray, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t CompareRects(const RECTF* rect1, const RECTF* rect2) {
|
||||
|
|
@ -30,6 +122,10 @@ int32_t CompareRects(const RECTF* rect1, const RECTF* rect2) {
|
|||
&& rect1->top == rect2->top;
|
||||
}
|
||||
|
||||
void DeleteCombinedRect(TSGrowableArray<RECTF>* combinedArray, uint32_t index) {
|
||||
DeleteRect(&(*combinedArray)[index]);
|
||||
}
|
||||
|
||||
void DeleteRect(RECTF* rect) {
|
||||
rect->left = std::numeric_limits<float>::max();
|
||||
rect->bottom = std::numeric_limits<float>::max();
|
||||
|
|
@ -37,37 +133,249 @@ void DeleteRect(RECTF* rect) {
|
|||
rect->top = std::numeric_limits<float>::max();
|
||||
}
|
||||
|
||||
void FragmentSourceRectangles(TSGrowableArray<SOURCE>* sourceArray, uint32_t firstIndex, uint32_t lastIndex, int32_t previousOverlap, const RECTF* rect, void* param, int32_t sequence) {
|
||||
if (firstIndex >= lastIndex) {
|
||||
AddSourceRect(sourceArray, rect, param, sequence, 0x1 | (previousOverlap ? 0x2 : 0x0));
|
||||
int SortFoundParamsCallback(const void* elem1, const void* elem2) {
|
||||
const FOUNDPARAM* param1 = static_cast<const FOUNDPARAM*>(elem1);
|
||||
const FOUNDPARAM* param2 = static_cast<const FOUNDPARAM*>(elem2);
|
||||
|
||||
return param1->sequence - param2->sequence;
|
||||
}
|
||||
|
||||
void FindSourceParams(RGN* rgnptr, const RECTF* rect) {
|
||||
if (CompareRects(rect, &rgnptr->foundparamsrect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto overlapsExisting = previousOverlap;
|
||||
rgnptr->foundparams.SetCount(0);
|
||||
uint32_t sourceRects = rgnptr->source.Count();
|
||||
uint32_t params = 0;
|
||||
|
||||
for (uint32_t i = firstIndex; i < lastIndex; i++) {
|
||||
auto source = &(*sourceArray)[i];
|
||||
|
||||
if (CheckForIntersection(rect, &source->rect)) {
|
||||
if (!CompareRects(rect, &source->rect)) {
|
||||
break;
|
||||
}
|
||||
|
||||
source->flags |= 0x2;
|
||||
overlapsExisting = 1;
|
||||
for (uint32_t i = 0; i < sourceRects; i++) {
|
||||
if (!CheckForIntersection(rect, &rgnptr->source[i].rect)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i + 1 == lastIndex) {
|
||||
AddSourceRect(sourceArray, rect, param, sequence, 0x1 | (previousOverlap ? 0x2 : 0x0));
|
||||
int32_t sequence = rgnptr->source[i].sequence;
|
||||
int32_t found = 0;
|
||||
|
||||
for (uint32_t j = 0; j < params; j++) {
|
||||
if (rgnptr->foundparams[j].sequence == sequence) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
FOUNDPARAM* newParam = rgnptr->foundparams.New();
|
||||
newParam->param = rgnptr->source[i].param;
|
||||
newParam->sequence = sequence;
|
||||
params++;
|
||||
}
|
||||
}
|
||||
|
||||
std::qsort(rgnptr->foundparams.Ptr(), rgnptr->foundparams.Count(), sizeof(FOUNDPARAM), SortFoundParamsCallback);
|
||||
rgnptr->foundparamsrect = *rect;
|
||||
}
|
||||
|
||||
void FragmentCombinedRectangles(TSGrowableArray<RECTF>* combinedArray, uint32_t firstIndex, uint32_t lastIndex, const RECTF* rect) {
|
||||
uint32_t index;
|
||||
RECTF* checkRect;
|
||||
|
||||
for (index = firstIndex; index < lastIndex; index++) {
|
||||
checkRect = &(*combinedArray)[index];
|
||||
if (CheckForIntersection(rect, checkRect)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index >= lastIndex) {
|
||||
AddCombinedRect(combinedArray, rect);
|
||||
return;
|
||||
}
|
||||
|
||||
RECTF newrect[4];
|
||||
|
||||
#if defined(WHOA_RECT_USES_SCREEN_COORDINATES)
|
||||
newrect[0] = { rect->left, rect->top, rect->right, checkRect->top };
|
||||
newrect[1] = { rect->left, checkRect->bottom, rect->right, rect->bottom };
|
||||
newrect[2] = {
|
||||
rect->left,
|
||||
std::max(checkRect->top, rect->top),
|
||||
checkRect->left,
|
||||
std::min(checkRect->bottom, rect->bottom)
|
||||
};
|
||||
newrect[3] = {
|
||||
checkRect->right,
|
||||
std::max(checkRect->top, rect->top),
|
||||
rect->right,
|
||||
std::min(checkRect->bottom, rect->bottom)
|
||||
};
|
||||
#else
|
||||
newrect[0] = { rect->left, rect->bottom, rect->right, checkRect->bottom };
|
||||
newrect[1] = { rect->left, checkRect->top, rect->right, rect->top };
|
||||
newrect[2] = {
|
||||
rect->left,
|
||||
std::max(checkRect->bottom, rect->bottom),
|
||||
checkRect->left,
|
||||
std::min(checkRect->top, rect->top)
|
||||
};
|
||||
newrect[3] = {
|
||||
checkRect->right,
|
||||
std::max(checkRect->bottom, rect->bottom),
|
||||
rect->right,
|
||||
std::min(checkRect->top, rect->top)
|
||||
};
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
if (!IsNullRect(&newrect[i])) {
|
||||
FragmentCombinedRectangles(combinedArray, index + 1, lastIndex, &newrect[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FragmentSourceRectangles(TSGrowableArray<SOURCE>* sourceArray, uint32_t firstIndex, uint32_t lastIndex, int32_t previousOverlap, const RECTF* rect, void* param, int32_t sequence) {
|
||||
auto overlapsExisting = previousOverlap;
|
||||
|
||||
for (uint32_t index = firstIndex; index < lastIndex; index++) {
|
||||
RECTF* checkRect = &(*sourceArray)[index].rect;
|
||||
|
||||
if (CheckForIntersection(rect, checkRect)) {
|
||||
if (CompareRects(rect, checkRect)) {
|
||||
(*sourceArray)[index].flags |= SF_OVERLAPS;
|
||||
overlapsExisting = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
const RECTF* overlapRect[2] = { rect, checkRect };
|
||||
|
||||
uint32_t minLeft = rect->left > checkRect->left ? 1 : 0;
|
||||
uint32_t maxLeft = checkRect->left > rect->left ? 1 : 0;
|
||||
uint32_t minBottom = rect->bottom > checkRect->bottom ? 1 : 0;
|
||||
uint32_t maxBottom = checkRect->bottom > rect->bottom ? 1 : 0;
|
||||
uint32_t minRight = rect->right > checkRect->right ? 1 : 0;
|
||||
uint32_t maxRight = checkRect->right > rect->right ? 1 : 0;
|
||||
uint32_t minTop = rect->top > checkRect->top ? 1 : 0;
|
||||
uint32_t maxTop = checkRect->top > rect->top ? 1 : 0;
|
||||
|
||||
RECTF newRect[5];
|
||||
|
||||
#if defined(WHOA_RECT_USES_SCREEN_COORDINATES)
|
||||
newRect[0] = {
|
||||
overlapRect[minTop]->left,
|
||||
overlapRect[minTop]->top,
|
||||
overlapRect[minTop]->right,
|
||||
overlapRect[maxTop]->top,
|
||||
};
|
||||
|
||||
newRect[1] = {
|
||||
overlapRect[maxBottom]->left,
|
||||
overlapRect[minBottom]->bottom,
|
||||
overlapRect[maxBottom]->right,
|
||||
overlapRect[maxBottom]->bottom,
|
||||
};
|
||||
|
||||
newRect[2] = {
|
||||
overlapRect[minLeft]->left,
|
||||
overlapRect[maxTop]->top,
|
||||
overlapRect[maxLeft]->left,
|
||||
overlapRect[minBottom]->bottom,
|
||||
};
|
||||
|
||||
newRect[3] = {
|
||||
overlapRect[minRight]->right,
|
||||
overlapRect[maxTop]->top,
|
||||
overlapRect[maxRight]->right,
|
||||
overlapRect[minBottom]->bottom,
|
||||
};
|
||||
|
||||
newRect[4] = {
|
||||
overlapRect[maxLeft]->left,
|
||||
overlapRect[maxTop]->top,
|
||||
overlapRect[minRight]->right,
|
||||
overlapRect[minBottom]->bottom,
|
||||
};
|
||||
#else
|
||||
newRect[0] = {
|
||||
overlapRect[minBottom]->left,
|
||||
overlapRect[minBottom]->bottom,
|
||||
overlapRect[minBottom]->right,
|
||||
overlapRect[maxBottom]->bottom,
|
||||
};
|
||||
|
||||
newRect[1] = {
|
||||
overlapRect[maxTop]->left,
|
||||
overlapRect[minTop]->top,
|
||||
overlapRect[maxTop]->right,
|
||||
overlapRect[maxTop]->top,
|
||||
};
|
||||
|
||||
newRect[2] = {
|
||||
overlapRect[minLeft]->left,
|
||||
overlapRect[maxBottom]->bottom,
|
||||
overlapRect[maxLeft]->left,
|
||||
overlapRect[minTop]->top,
|
||||
};
|
||||
|
||||
newRect[3] = {
|
||||
overlapRect[minRight]->right,
|
||||
overlapRect[maxBottom]->bottom,
|
||||
overlapRect[maxRight]->right,
|
||||
overlapRect[minTop]->top,
|
||||
};
|
||||
|
||||
newRect[4] = {
|
||||
overlapRect[maxLeft]->left,
|
||||
overlapRect[maxBottom]->bottom,
|
||||
overlapRect[minRight]->right,
|
||||
overlapRect[minTop]->top,
|
||||
};
|
||||
#endif
|
||||
|
||||
int32_t overlaps[5][2];
|
||||
for (uint32_t j = 0; j < 5; j++) {
|
||||
if (IsNullRect(&newRect[j])) {
|
||||
overlaps[j][1] = 0;
|
||||
overlaps[j][0] = 0;
|
||||
}
|
||||
else {
|
||||
for (uint32_t k = 0; k < 2; k++) {
|
||||
overlaps[j][k] = CheckForIntersection(&newRect[j], overlapRect[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < 5; j++) {
|
||||
if (overlaps[j][0]) {
|
||||
FragmentSourceRectangles(
|
||||
sourceArray,
|
||||
index + 1,
|
||||
lastIndex,
|
||||
overlapsExisting || overlaps[j][1],
|
||||
&newRect[j],
|
||||
param,
|
||||
sequence);
|
||||
}
|
||||
|
||||
if (overlaps[j][1]) {
|
||||
uint32_t newFlags = (*sourceArray)[index].flags & ~SF_TEMPMASK;
|
||||
newFlags |= overlaps[j][0] ? SF_OVERLAPS : SF_NONE;
|
||||
|
||||
AddSourceRect(sourceArray, &newRect[j], (*sourceArray)[index].param, (*sourceArray)[index].sequence, newFlags);
|
||||
}
|
||||
}
|
||||
DeleteSourceRect(sourceArray, index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
AddSourceRect(sourceArray, rect, param, sequence, SF_ADDING | (overlapsExisting ? SF_OVERLAPS : SF_NONE));
|
||||
}
|
||||
|
||||
int32_t IsNullRect(RECTF* rect) {
|
||||
int32_t IsNullRect(const RECTF* rect) {
|
||||
#if defined(WHOA_RECT_USES_SCREEN_COORDINATES)
|
||||
return rect->left >= rect->right || rect->top >= rect->bottom;
|
||||
#else
|
||||
return rect->left >= rect->right || rect->bottom >= rect->top;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ClearRegion(RGN* rgn) {
|
||||
|
|
@ -92,24 +400,24 @@ void DeleteSourceRect(TSGrowableArray<SOURCE>* sourceArray, uint32_t index) {
|
|||
DeleteRect(&source->rect);
|
||||
source->param = nullptr;
|
||||
source->sequence = -1;
|
||||
source->flags = 0x0;
|
||||
source->flags = SF_NONE;
|
||||
}
|
||||
|
||||
void OptimizeSource(TSGrowableArray<SOURCE>* sourceArray) {
|
||||
for (uint32_t i = 0; i < sourceArray->Count(); i++) {
|
||||
auto source = &(*sourceArray)[i];
|
||||
for (uint32_t index = 0; index < sourceArray->Count(); ) {
|
||||
auto source = &(*sourceArray)[index];
|
||||
|
||||
if (IsNullRect(&source->rect)) {
|
||||
// Set current (null) element to last element
|
||||
auto last = &(*sourceArray)[sourceArray->Count() - 1];
|
||||
(*sourceArray)[i] = *last;
|
||||
|
||||
// Decrement index by 1 to force null check on copied last element on next tick
|
||||
i--;
|
||||
(*sourceArray)[index] = *last;
|
||||
|
||||
// Shrink by 1 (to account for the removal of the null element)
|
||||
sourceArray->SetCount(sourceArray->Count() - 1);
|
||||
}
|
||||
else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -117,81 +425,142 @@ void ProcessBooleanOperation(TSGrowableArray<SOURCE>* sourceArray, int32_t combi
|
|||
for (uint32_t i = 0; i < sourceArray->Count(); i++) {
|
||||
auto source = &(*sourceArray)[i];
|
||||
|
||||
int32_t remove = 0;
|
||||
switch (combineMode) {
|
||||
case 1: {
|
||||
if ((~source->flags >> 1) & 0x1) {
|
||||
DeleteSourceRect(sourceArray, i);
|
||||
}
|
||||
|
||||
case SRGN_AND:
|
||||
remove = !(source->flags & SF_OVERLAPS);
|
||||
break;
|
||||
case SRGN_XOR:
|
||||
remove = source->flags & SF_OVERLAPS;
|
||||
break;
|
||||
case SRGN_DIFF:
|
||||
remove = source->flags & (SF_ADDING | SF_OVERLAPS);
|
||||
break;
|
||||
case SRGN_COPY:
|
||||
remove = source->flags & SF_ADDING;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
if (source->flags & 0x2) {
|
||||
DeleteSourceRect(sourceArray, i);
|
||||
}
|
||||
|
||||
break;
|
||||
if (remove) {
|
||||
DeleteSourceRect(sourceArray, i);
|
||||
}
|
||||
|
||||
case 4: {
|
||||
if (source->flags & (0x1 | 0x2)) {
|
||||
DeleteSourceRect(sourceArray, i);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 5: {
|
||||
if (source->flags & 0x1) {
|
||||
DeleteSourceRect(sourceArray, i);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
source->flags = 0x0;
|
||||
source->flags = SF_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void SRgnCombineRectf(HSRGN handle, RECTF* rect, void* param, int32_t combineMode) {
|
||||
STORM_ASSERT(handle);
|
||||
STORM_ASSERT(rect);
|
||||
STORM_ASSERT(combineMode >= 1);
|
||||
STORM_ASSERT(combineMode <= 6);
|
||||
int SortRectCallback(const void* elem1, const void* elem2) {
|
||||
const RECTF* rct1 = static_cast<const RECTF*>(elem1);
|
||||
const RECTF* rct2 = static_cast<const RECTF*>(elem2);
|
||||
|
||||
#if defined(WHOA_RECT_USES_SCREEN_COORDINATES)
|
||||
double result = rct1->bottom == rct2->bottom ? rct1->left - rct2->left : rct1->bottom - rct2->bottom;
|
||||
#else
|
||||
double result = rct1->top == rct2->top ? rct1->left - rct2->left : rct1->top - rct2->top;
|
||||
#endif
|
||||
|
||||
if (result > 0.0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (result < 0.0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ProduceCombinedRectangles(RGN* rgn) {
|
||||
rgn->combined.SetCount(0);
|
||||
|
||||
uint32_t sourcerects = rgn->source.Count();
|
||||
SOURCE* sourcearray = rgn->source.Ptr();
|
||||
for (uint32_t i = 0; i < sourcerects; i++) {
|
||||
if (!(sourcearray[i].flags & SF_PARAMONLY)) {
|
||||
FragmentCombinedRectangles(&rgn->combined, 0, rgn->combined.Count(), &sourcearray[i].rect);
|
||||
}
|
||||
}
|
||||
|
||||
CombineRectangles(&rgn->combined);
|
||||
|
||||
std::qsort(rgn->combined.Ptr(), rgn->combined.Count(), sizeof(RECTF), SortRectCallback);
|
||||
|
||||
for (uint32_t i = rgn->combined.Count(); i > 0; i = rgn->combined.Count()) {
|
||||
if (!IsNullRect(&rgn->combined[i-1])) {
|
||||
break;
|
||||
}
|
||||
|
||||
rgn->combined.SetCount(i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void STORMAPI SRgnCombineRectf(HSRGN handle, const RECTF* rect, void* param, int32_t combineMode) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE(rect);
|
||||
STORM_VALIDATE(combineMode >= 1);
|
||||
STORM_VALIDATE(combineMode <= 6);
|
||||
STORM_VALIDATE_END_VOID;
|
||||
|
||||
HLOCKEDRGN lockedHandle;
|
||||
auto rgn = s_rgntable.Lock(handle, &lockedHandle, 0);
|
||||
if (!rgn) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (combineMode == SRGN_OR || combineMode == SRGN_PARAMONLY) {
|
||||
if (!IsNullRect(rect)) {
|
||||
rgn->sequence++;
|
||||
AddSourceRect(&rgn->source, rect, param, rgn->sequence, combineMode == SRGN_PARAMONLY ? SF_PARAMONLY : SF_NONE);
|
||||
}
|
||||
} else {
|
||||
if (!IsNullRect(rect)) {
|
||||
rgn->sequence++;
|
||||
FragmentSourceRectangles(&rgn->source, 0, rgn->source.Count(), 0, rect, param, rgn->sequence);
|
||||
}
|
||||
|
||||
ProcessBooleanOperation(&rgn->source, combineMode);
|
||||
OptimizeSource(&rgn->source);
|
||||
}
|
||||
|
||||
InvalidateRegion(rgn);
|
||||
s_rgntable.Unlock(lockedHandle);
|
||||
}
|
||||
|
||||
void STORMAPI SRgnCombineRecti(HSRGN handle, const RECT* rect, void* param, int32_t combineMode) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(rect);
|
||||
STORM_VALIDATE_END_VOID;
|
||||
|
||||
// NOTE: top and bottom get flipped, this is a bug in Storm
|
||||
RECTF rectf = {
|
||||
static_cast<float>(rect->left),
|
||||
static_cast<float>(rect->top),
|
||||
static_cast<float>(rect->right),
|
||||
static_cast<float>(rect->bottom)
|
||||
};
|
||||
SRgnCombineRectf(handle, &rectf, param, combineMode);
|
||||
}
|
||||
|
||||
void STORMAPI SRgnClear(HSRGN handle) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE_END_VOID;
|
||||
|
||||
HLOCKEDRGN lockedHandle;
|
||||
auto rgn = s_rgntable.Lock(handle, &lockedHandle, 0);
|
||||
|
||||
if (rgn) {
|
||||
if (combineMode == 2 || combineMode == 6) {
|
||||
if (!IsNullRect(rect)) {
|
||||
rgn->sequence++;
|
||||
AddSourceRect(&rgn->source, rect, param, rgn->sequence, combineMode == 6 ? 0x10000 : 0x0);
|
||||
}
|
||||
} else {
|
||||
if (!IsNullRect(rect)) {
|
||||
rgn->sequence++;
|
||||
FragmentSourceRectangles(&rgn->source, 0, rgn->source.Count(), 0, rect, param, rgn->sequence);
|
||||
}
|
||||
|
||||
ProcessBooleanOperation(&rgn->source, combineMode);
|
||||
OptimizeSource(&rgn->source);
|
||||
}
|
||||
|
||||
InvalidateRegion(rgn);
|
||||
ClearRegion(rgn);
|
||||
s_rgntable.Unlock(lockedHandle);
|
||||
}
|
||||
|
||||
s_rgntable.Unlock(lockedHandle);
|
||||
}
|
||||
|
||||
void SRgnCreate(HSRGN* handlePtr, uint32_t reserved) {
|
||||
STORM_ASSERT(handlePtr);
|
||||
STORM_ASSERT(!reserved);
|
||||
void STORMAPI SRgnCreate(HSRGN* handlePtr, uint32_t reserved) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(handlePtr);
|
||||
STORM_VALIDATE(!reserved);
|
||||
STORM_VALIDATE_END_VOID;
|
||||
|
||||
HLOCKEDRGN lockedHandle = nullptr;
|
||||
auto rgn = s_rgntable.NewLock(handlePtr, &lockedHandle);
|
||||
|
|
@ -201,37 +570,81 @@ void SRgnCreate(HSRGN* handlePtr, uint32_t reserved) {
|
|||
s_rgntable.Unlock(lockedHandle);
|
||||
}
|
||||
|
||||
void SRgnDelete(HSRGN handle) {
|
||||
STORM_ASSERT(handle);
|
||||
void STORMAPI SRgnDelete(HSRGN handle) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE_END_VOID;
|
||||
|
||||
s_rgntable.Delete(handle);
|
||||
}
|
||||
|
||||
void SRgnGetBoundingRectf(HSRGN handle, RECTF* rect) {
|
||||
STORM_ASSERT(handle);
|
||||
STORM_ASSERT(rect);
|
||||
void STORMAPI SRgnDestroy() {
|
||||
s_rgntable.Destroy();
|
||||
}
|
||||
|
||||
rect->left = std::numeric_limits<float>::max();
|
||||
rect->bottom = std::numeric_limits<float>::max();
|
||||
rect->right = std::numeric_limits<float>::min();
|
||||
rect->top = std::numeric_limits<float>::min();
|
||||
void STORMAPI SRgnDuplicate(HSRGN origHandle, HSRGN* handle, uint32_t reserved) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(handle);
|
||||
*handle = nullptr;
|
||||
|
||||
STORM_VALIDATE(origHandle);
|
||||
STORM_VALIDATE(reserved == 0);
|
||||
STORM_VALIDATE_END_VOID;
|
||||
|
||||
HLOCKEDRGN origlockedhandle;
|
||||
auto rgn = s_rgntable.Lock(origHandle, &origlockedhandle, 0);
|
||||
|
||||
if (!rgn) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(WHOA_STORM_C_CRIT_SECT_RECURSIVE)
|
||||
HLOCKEDRGN newlockedhandle;
|
||||
|
||||
auto newrgn = s_rgntable.NewLock(handle, &newlockedhandle);
|
||||
*newrgn = *rgn;
|
||||
s_rgntable.Unlock(newlockedhandle);
|
||||
#else
|
||||
auto newrgn = s_rgntable.New(handle);
|
||||
*newrgn = *rgn;
|
||||
#endif
|
||||
|
||||
s_rgntable.Unlock(origlockedhandle);
|
||||
}
|
||||
|
||||
void STORMAPI SRgnGetBoundingRectf(HSRGN handle, RECTF* rect) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE(rect);
|
||||
STORM_VALIDATE_END_VOID;
|
||||
|
||||
*rect = {
|
||||
std::numeric_limits<float>::max(),
|
||||
std::numeric_limits<float>::max(),
|
||||
std::numeric_limits<float>::min(),
|
||||
std::numeric_limits<float>::min(),
|
||||
};
|
||||
|
||||
HLOCKEDRGN lockedHandle;
|
||||
auto rgn = s_rgntable.Lock(handle, &lockedHandle, 0);
|
||||
|
||||
if (!rgn) {
|
||||
s_rgntable.Unlock(lockedHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < rgn->source.Count(); i++) {
|
||||
auto source = &rgn->source[i];
|
||||
|
||||
if (!(source->flags & 0x10000)) {
|
||||
if (!(source->flags & SF_PARAMONLY)) {
|
||||
rect->left = std::min(source->rect.left, rect->left);
|
||||
rect->bottom = std::min(source->rect.bottom, rect->bottom);
|
||||
rect->right = std::max(source->rect.right, rect->right);
|
||||
|
||||
#if defined(WHOA_RECT_USES_SCREEN_COORDINATES)
|
||||
rect->top = std::min(source->rect.top, rect->top);
|
||||
rect->bottom = std::max(source->rect.bottom, rect->bottom);
|
||||
#else
|
||||
rect->bottom = std::min(source->rect.bottom, rect->bottom);
|
||||
rect->top = std::max(source->rect.top, rect->top);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -244,3 +657,239 @@ void SRgnGetBoundingRectf(HSRGN handle, RECTF* rect) {
|
|||
rect->top = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void STORMAPI SRgnGetBoundingRecti(HSRGN handle, RECT* rect) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(rect);
|
||||
STORM_VALIDATE_END_VOID;
|
||||
|
||||
RECTF rectf;
|
||||
SRgnGetBoundingRectf(handle, &rectf);
|
||||
|
||||
rect->left = static_cast<int32_t>(rectf.left);
|
||||
rect->right = static_cast<int32_t>(rectf.right);
|
||||
#if defined(WHOA_RECT_USES_SCREEN_COORDINATES)
|
||||
rect->top = static_cast<int32_t>(rectf.top);
|
||||
rect->bottom = static_cast<int32_t>(rectf.bottom);
|
||||
#else
|
||||
// NOTE: top and bottom get flipped, this is a bug in Storm
|
||||
rect->top = static_cast<int32_t>(rectf.bottom);
|
||||
rect->bottom = static_cast<int32_t>(rectf.top);
|
||||
#endif
|
||||
}
|
||||
|
||||
void STORMAPI SRgnGetRectParamsf(HSRGN handle, const RECTF* rect, uint32_t* numParams, void** buffer) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE(rect);
|
||||
STORM_VALIDATE(numParams);
|
||||
STORM_VALIDATE_END_VOID;
|
||||
|
||||
if (IsNullRect(rect)) {
|
||||
*numParams = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
HLOCKEDRGN lockedHandle;
|
||||
auto rgn = s_rgntable.Lock(handle, &lockedHandle, 0);
|
||||
if (!rgn) {
|
||||
*numParams = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (rgn->dirty) {
|
||||
ProduceCombinedRectangles(rgn);
|
||||
rgn->dirty = 0;
|
||||
}
|
||||
|
||||
FindSourceParams(rgn, rect);
|
||||
|
||||
if (buffer) {
|
||||
*numParams = std::min(*numParams, rgn->foundparams.Count());
|
||||
FOUNDPARAM* foundArray = rgn->foundparams.Ptr();
|
||||
|
||||
for (uint32_t i = 0; i < *numParams; i++) {
|
||||
buffer[i] = foundArray[i].param;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*numParams = rgn->foundparams.Count();
|
||||
}
|
||||
|
||||
s_rgntable.Unlock(lockedHandle);
|
||||
}
|
||||
|
||||
void STORMAPI SRgnGetRectParamsi(HSRGN handle, const RECT* rect, uint32_t* numParams, void** buffer) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(rect);
|
||||
STORM_VALIDATE_END_VOID;
|
||||
|
||||
// NOTE: top and bottom get flipped, this is a bug in Storm
|
||||
RECTF rectf = {
|
||||
static_cast<float>(rect->left),
|
||||
static_cast<float>(rect->top),
|
||||
static_cast<float>(rect->right),
|
||||
static_cast<float>(rect->bottom)
|
||||
};
|
||||
SRgnGetRectParamsf(handle, &rectf, numParams, buffer);
|
||||
}
|
||||
|
||||
void STORMAPI SRgnGetRectsf(HSRGN handle, uint32_t* numRects, RECTF* buffer) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE(numRects);
|
||||
STORM_VALIDATE_END_VOID;
|
||||
|
||||
HLOCKEDRGN lockedHandle;
|
||||
auto rgn = s_rgntable.Lock(handle, &lockedHandle, 0);
|
||||
if (!rgn) {
|
||||
*numRects = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (rgn->dirty) {
|
||||
ProduceCombinedRectangles(rgn);
|
||||
rgn->dirty = 0;
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
*numRects = std::min(*numRects, rgn->combined.Count());
|
||||
memcpy(buffer, rgn->combined.Ptr(), sizeof(rgn->combined.Ptr()[0]) * *numRects);
|
||||
}
|
||||
else {
|
||||
*numRects = rgn->combined.Count();
|
||||
}
|
||||
|
||||
s_rgntable.Unlock(lockedHandle);
|
||||
}
|
||||
|
||||
void STORMAPI SRgnGetRectsi(HSRGN handle, uint32_t* numRects, RECT* buffer) {
|
||||
RECTF* bufferf = reinterpret_cast<RECTF*>(buffer);
|
||||
SRgnGetRectsf(handle, numRects, bufferf);
|
||||
if (buffer) {
|
||||
for (uint32_t i = 0; i < *numRects; i++) {
|
||||
#if defined(WHOA_RECT_USES_SCREEN_COORDINATES)
|
||||
buffer[i].top = static_cast<int32_t>(bufferf[i].top);
|
||||
buffer[i].bottom = static_cast<int32_t>(bufferf[i].bottom);
|
||||
#else
|
||||
float bottom = bufferf[i].bottom;
|
||||
float top = bufferf[i].top;
|
||||
|
||||
buffer[i].bottom = static_cast<int32_t>(bottom);
|
||||
buffer[i].top = static_cast<int32_t>(top);
|
||||
#endif
|
||||
buffer[i].left = static_cast<int32_t>(bufferf[i].left);
|
||||
buffer[i].right = static_cast<int32_t>(bufferf[i].right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t STORMAPI SRgnIsPointInRegionf(HSRGN handle, float x, float y) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
HLOCKEDRGN lockedHandle;
|
||||
auto rgn = s_rgntable.Lock(handle, &lockedHandle, 0);
|
||||
if (!rgn) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t result = 0;
|
||||
|
||||
SOURCE* sourceArray = rgn->source.Ptr();
|
||||
uint32_t sourceRects = rgn->source.Count();
|
||||
for (uint32_t i = 0; i < sourceRects; i++) {
|
||||
if (!(sourceArray[i].flags & SF_PARAMONLY)) {
|
||||
#if defined(WHOA_RECT_USES_SCREEN_COORDINATES)
|
||||
if (x >= sourceArray[i].rect.left && y >= sourceArray[i].rect.top &&
|
||||
x < sourceArray[i].rect.right && y < sourceArray[i].rect.bottom) {
|
||||
#else
|
||||
if (x >= sourceArray[i].rect.left && y >= sourceArray[i].rect.bottom &&
|
||||
x < sourceArray[i].rect.right && y < sourceArray[i].rect.top) {
|
||||
#endif
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_rgntable.Unlock(lockedHandle);
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t STORMAPI SRgnIsPointInRegioni(HSRGN handle, int32_t x, int32_t y) {
|
||||
return SRgnIsPointInRegionf(handle, static_cast<float>(x), static_cast<float>(y));
|
||||
}
|
||||
|
||||
int32_t STORMAPI SRgnIsRectInRegionf(HSRGN handle, const RECTF* rect) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE(rect);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
HLOCKEDRGN lockedHandle;
|
||||
auto rgn = s_rgntable.Lock(handle, &lockedHandle, 0);
|
||||
if (!rgn) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t result = 0;
|
||||
|
||||
SOURCE* sourceArray = rgn->source.Ptr();
|
||||
uint32_t sourceRects = rgn->source.Count();
|
||||
for (uint32_t i = 0; i < sourceRects; i++) {
|
||||
if (!(sourceArray[i].flags & SF_PARAMONLY)) {
|
||||
if (CheckForIntersection(rect, &sourceArray[i].rect)) {
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_rgntable.Unlock(lockedHandle);
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t STORMAPI SRgnIsRectInRegioni(HSRGN handle, const RECT* rect) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(rect);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
// NOTE: top and bottom get flipped, this is a bug in Storm
|
||||
RECTF rectf = {
|
||||
static_cast<float>(rect->left),
|
||||
static_cast<float>(rect->top),
|
||||
static_cast<float>(rect->right),
|
||||
static_cast<float>(rect->bottom)
|
||||
};
|
||||
return SRgnIsRectInRegionf(handle, &rectf);
|
||||
}
|
||||
|
||||
void STORMAPI SRgnOffsetf(HSRGN handle, float xoffset, float yoffset) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE_END_VOID;
|
||||
|
||||
HLOCKEDRGN lockedHandle;
|
||||
auto rgn = s_rgntable.Lock(handle, &lockedHandle, 0);
|
||||
if (!rgn) {
|
||||
return;
|
||||
}
|
||||
|
||||
SOURCE* sourceArray = rgn->source.Ptr();
|
||||
uint32_t sourceRects = rgn->source.Count();
|
||||
for (uint32_t i = 0; i < sourceRects; i++) {
|
||||
sourceArray[i].rect.left += xoffset;
|
||||
sourceArray[i].rect.bottom += yoffset;
|
||||
sourceArray[i].rect.right += xoffset;
|
||||
sourceArray[i].rect.top += yoffset;
|
||||
}
|
||||
InvalidateRegion(rgn);
|
||||
|
||||
s_rgntable.Unlock(lockedHandle);
|
||||
}
|
||||
|
||||
void STORMAPI SRgnOffseti(HSRGN handle, int32_t xoffset, int32_t yoffset) {
|
||||
SRgnOffsetf(handle, static_cast<float>(xoffset), static_cast<float>(yoffset));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,14 +2,44 @@
|
|||
#define STORM_REGION_HPP
|
||||
|
||||
#include "storm/region/Types.hpp"
|
||||
#include <cstdint>
|
||||
#include "Core.hpp"
|
||||
|
||||
void SRgnCombineRectf(HSRGN handle, RECTF* rect, void* param, int32_t combineMode);
|
||||
void STORMAPI SRgnClear(HSRGN handle);
|
||||
|
||||
void SRgnCreate(HSRGN* handlePtr, uint32_t reserved);
|
||||
void STORMAPI SRgnCombineRectf(HSRGN handle, const RECTF* rect, void* param, int32_t combineMode);
|
||||
|
||||
void SRgnDelete(HSRGN handle);
|
||||
void STORMAPI SRgnCombineRecti(HSRGN handle, const RECT* rect, void* param, int32_t combineMode);
|
||||
|
||||
void SRgnGetBoundingRectf(HSRGN handle, RECTF* rect);
|
||||
void STORMAPI SRgnCreate(HSRGN* handlePtr, uint32_t reserved = 0);
|
||||
|
||||
void STORMAPI SRgnDelete(HSRGN handle);
|
||||
|
||||
void STORMAPI SRgnDestroy();
|
||||
|
||||
void STORMAPI SRgnDuplicate(HSRGN origHandle, HSRGN* handle, uint32_t reserved = 0);
|
||||
|
||||
void STORMAPI SRgnGetBoundingRectf(HSRGN handle, RECTF* rect);
|
||||
|
||||
void STORMAPI SRgnGetBoundingRecti(HSRGN handle, RECT* rect);
|
||||
|
||||
void STORMAPI SRgnGetRectParamsf(HSRGN handle, const RECTF* rect, uint32_t* numParams, void** buffer);
|
||||
|
||||
void STORMAPI SRgnGetRectParamsi(HSRGN handle, const RECT* rect, uint32_t* numParams, void** buffer);
|
||||
|
||||
void STORMAPI SRgnGetRectsf(HSRGN handle, uint32_t* numRects, RECTF* buffer);
|
||||
|
||||
void STORMAPI SRgnGetRectsi(HSRGN handle, uint32_t* numRects, RECT* buffer);
|
||||
|
||||
int32_t STORMAPI SRgnIsPointInRegionf(HSRGN handle, float x, float y);
|
||||
|
||||
int32_t STORMAPI SRgnIsPointInRegioni(HSRGN handle, int32_t x, int32_t y);
|
||||
|
||||
int32_t STORMAPI SRgnIsRectInRegionf(HSRGN handle, const RECTF* rect);
|
||||
|
||||
int32_t STORMAPI SRgnIsRectInRegioni(HSRGN handle, const RECT* rect);
|
||||
|
||||
void STORMAPI SRgnOffsetf(HSRGN handle, float xoffset, float yoffset);
|
||||
|
||||
void STORMAPI SRgnOffseti(HSRGN handle, int32_t xoffset, int32_t yoffset);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
381
storm/String.cpp
381
storm/String.cpp
|
|
@ -7,7 +7,6 @@
|
|||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
#include <string.h>
|
||||
|
|
@ -51,6 +50,20 @@ int32_t s_initialized;
|
|||
|
||||
double s_realDigit[20][10];
|
||||
|
||||
const uint32_t s_hashtable[16] = {
|
||||
0x486E26EE, 0xDCAA16B3, 0xE1918EEF, 0x202DAFDB,
|
||||
0x341C7DC7, 0x1C365303, 0x40EF2D37, 0x65FD5E49,
|
||||
0xD6057177, 0x904ECE93, 0x1C38024F, 0x98FD323B,
|
||||
0xE3061AE7, 0xA39B0FA1, 0x9797F25F, 0xE4444563,
|
||||
};
|
||||
|
||||
const uint64_t s_hashtable64[16] = {
|
||||
0x486E26EEDCAA16B3ULL, 0xE1918EEF202DAFDBULL, 0x341C7DC71C365303ULL, 0x40EF2D3765FD5E49ULL,
|
||||
0xD6057177904ECE93ULL, 0x1C38024F98FD323BULL, 0xE3061AE7A39B0FA1ULL, 0x9797F25FE4444563ULL,
|
||||
0xCD2EC20C8DC1B898ULL, 0x31759633799A306DULL, 0x8C2063852E6E9627ULL, 0x79237D9973922C66ULL,
|
||||
0x8728628D28628824ULL, 0x8F1F7E9625887795ULL, 0x296E3281389C0D60ULL, 0x6F4893CA61636542ULL,
|
||||
};
|
||||
|
||||
void GetNextTextUpper(uint32_t* orig, const char** string, uint32_t* upper) {
|
||||
uint8_t byte = **string;
|
||||
int32_t v3 = bytesFromUTF8[byte];
|
||||
|
|
@ -177,7 +190,7 @@ void InitializeFloatDigits() {
|
|||
}
|
||||
}
|
||||
|
||||
size_t ISStrVPrintf(const char* format, va_list va, char* dest, size_t maxchars) {
|
||||
size_t ISStrVPrintf(char* dest, size_t maxchars, const char* format, va_list va) {
|
||||
if (!maxchars) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -200,14 +213,14 @@ size_t ISStrVPrintf(const char* format, va_list va, char* dest, size_t maxchars)
|
|||
return result;
|
||||
}
|
||||
|
||||
void SStrInitialize() {
|
||||
void STORMAPI SStrInitialize() {
|
||||
if (!s_initialized) {
|
||||
InitializeFloatDigits();
|
||||
s_initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
char* SStrChr(char* string, char search) {
|
||||
char* STORMAPI SStrChr(char* string, char search) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
|
@ -227,7 +240,7 @@ char* SStrChr(char* string, char search) {
|
|||
return string;
|
||||
}
|
||||
|
||||
const char* SStrChr(const char* string, char search) {
|
||||
const char* STORMAPI SStrChr(const char* string, char search) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
|
@ -247,7 +260,20 @@ const char* SStrChr(const char* string, char search) {
|
|||
return string;
|
||||
}
|
||||
|
||||
char* SStrChrR(char* string, char search) {
|
||||
const char* STORMAPI SStrChrBidir(const char* string, char search, int32_t reverse) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
if (reverse) {
|
||||
return SStrChrR(string, search);
|
||||
}
|
||||
else {
|
||||
return SStrChr(string, search);
|
||||
}
|
||||
}
|
||||
|
||||
char* STORMAPI SStrChrR(char* string, char search) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
|
@ -263,7 +289,7 @@ char* SStrChrR(char* string, char search) {
|
|||
return result;
|
||||
}
|
||||
|
||||
const char* SStrChrR(const char* string, char search) {
|
||||
const char* STORMAPI SStrChrR(const char* string, char search) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
|
@ -279,11 +305,21 @@ const char* SStrChrR(const char* string, char search) {
|
|||
return result;
|
||||
}
|
||||
|
||||
int32_t SStrCmp(const char* string1, const char* string2, size_t maxchars) {
|
||||
int32_t STORMAPI SStrCmp(const char* string1, const char* string2, size_t maxchars) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string1);
|
||||
STORM_VALIDATE(string2);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
return strncmp(string1, string2, maxchars);
|
||||
}
|
||||
|
||||
int32_t SStrCmpI(const char* string1, const char* string2, size_t maxchars) {
|
||||
int32_t STORMAPI SStrCmpI(const char* string1, const char* string2, size_t maxchars) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string1);
|
||||
STORM_VALIDATE(string2);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
return _strnicmp(string1, string2, maxchars);
|
||||
#endif
|
||||
|
|
@ -293,7 +329,7 @@ int32_t SStrCmpI(const char* string1, const char* string2, size_t maxchars) {
|
|||
#endif
|
||||
}
|
||||
|
||||
size_t SStrCopy(char* dest, const char* source, size_t destsize) {
|
||||
size_t STORMAPI SStrCopy(char* dest, const char* source, size_t destsize) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(dest);
|
||||
STORM_VALIDATE(source);
|
||||
|
|
@ -328,22 +364,15 @@ size_t SStrCopy(char* dest, const char* source, size_t destsize) {
|
|||
return static_cast<size_t>(destbuf - dest);
|
||||
}
|
||||
|
||||
size_t SStrNCopy(char* dest, const char* source, size_t maxchars, size_t destsize) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(dest);
|
||||
STORM_VALIDATE(source);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
auto length = strnlen(source, maxchars);
|
||||
if (destsize) {
|
||||
auto count = std::min(length, destsize - 1);
|
||||
memcpy(dest, source, count);
|
||||
dest[count] = '\0';
|
||||
}
|
||||
return length;
|
||||
void STORMAPI SStrDestroy() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
char* SStrDupA(const char* string, const char* filename, uint32_t linenumber) {
|
||||
char* STORMAPI SStrDupA(const char* string, const char* filename, uint32_t linenumber) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
size_t len = SStrLen(string) + 1;
|
||||
char* dup = static_cast<char*>(SMemAlloc(len, filename, linenumber, 0x0));
|
||||
memcpy(dup, string, len);
|
||||
|
|
@ -351,7 +380,43 @@ char* SStrDupA(const char* string, const char* filename, uint32_t linenumber) {
|
|||
return dup;
|
||||
}
|
||||
|
||||
uint32_t SStrHashHT(const char* string) {
|
||||
uint32_t STORMAPI SStrHash(const char* string, uint32_t flags, uint32_t seed) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
uint32_t result = seed ? seed : 0x7FED7FED;
|
||||
uint32_t adjust = 0xEEEEEEEE;
|
||||
uint32_t ch;
|
||||
|
||||
if (flags & SSTR_HASH_CASESENSITIVE) {
|
||||
for (; *string; string++) {
|
||||
ch = *string;
|
||||
|
||||
result = (s_hashtable[ch / 16] - s_hashtable[ch % 16]) ^ (adjust + result);
|
||||
adjust = 33 * adjust + result + ch + 3;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (; *string; string++) {
|
||||
ch = *string;
|
||||
|
||||
if (ch >= 'a' && ch <= 'z') {
|
||||
ch -= 32;
|
||||
}
|
||||
|
||||
if (ch == '/') {
|
||||
ch = '\\';
|
||||
}
|
||||
|
||||
result = (s_hashtable[ch / 16] - s_hashtable[ch % 16]) ^ (adjust + result);
|
||||
adjust = 33 * adjust + result + ch + 3;
|
||||
}
|
||||
}
|
||||
return result ? result : 1;
|
||||
}
|
||||
|
||||
uint32_t STORMAPI SStrHashHT(const char* string) {
|
||||
char normalized[0x400];
|
||||
char* buf = normalized;
|
||||
|
||||
|
|
@ -382,7 +447,51 @@ uint32_t SStrHashHT(const char* string) {
|
|||
return bjhash((uint8_t*)&normalized, length, 0);
|
||||
}
|
||||
|
||||
size_t SStrLen(const char* string) {
|
||||
int64_t STORMAPI SStrHash64(const char* string, uint32_t flags, int64_t seed) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
int64_t result = seed ? seed : 0x7FED7FED7FED7FEDLL;
|
||||
int64_t adjust = 0xEEEEEEEEEEEEEEEELL;
|
||||
uint32_t ch;
|
||||
|
||||
if (flags & SSTR_HASH_CASESENSITIVE) {
|
||||
for (; *string; string++) {
|
||||
ch = static_cast<uint8_t>(*string);
|
||||
|
||||
#if defined(WHOA_SSTRHASH64_SUBTRACTS)
|
||||
result = (s_hashtable64[ch / 16] - s_hashtable64[ch % 16]) ^ (adjust + result);
|
||||
#else
|
||||
result = (s_hashtable64[ch / 16] + s_hashtable64[ch % 16]) ^ (adjust + result);
|
||||
#endif
|
||||
adjust = 33 * adjust + result + ch + 3;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (; *string; string++) {
|
||||
ch = static_cast<uint8_t>(*string);
|
||||
|
||||
if (ch >= 'a' && ch <= 'z') {
|
||||
ch -= 32;
|
||||
}
|
||||
|
||||
if (ch == '/') {
|
||||
ch = '\\';
|
||||
}
|
||||
|
||||
#if defined(WHOA_SSTRHASH64_SUBTRACTS)
|
||||
result = (s_hashtable64[ch / 16] - s_hashtable64[ch % 16]) ^ (adjust + result);
|
||||
#else
|
||||
result = (s_hashtable64[ch / 16] + s_hashtable64[ch % 16]) ^ (adjust + result);
|
||||
#endif
|
||||
adjust = 33 * adjust + result + ch + 3;
|
||||
}
|
||||
}
|
||||
return result ? result : 1LL;
|
||||
}
|
||||
|
||||
size_t STORMAPI SStrLen(const char* string) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
|
@ -395,16 +504,18 @@ size_t SStrLen(const char* string) {
|
|||
return stringEnd - string;
|
||||
}
|
||||
|
||||
void SStrLower(char* string) {
|
||||
void STORMAPI SStrLower(char* string) {
|
||||
while (*string) {
|
||||
*string = static_cast<char>(tolower(*string));
|
||||
string++;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SStrPack(char* dest, const char* source, uint32_t destsize) {
|
||||
STORM_ASSERT(dest);
|
||||
STORM_ASSERT(source);
|
||||
uint32_t STORMAPI SStrPack(char* dest, const char* source, uint32_t destsize) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(dest);
|
||||
STORM_VALIDATE(source);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
if (!destsize) {
|
||||
return 0;
|
||||
|
|
@ -445,137 +556,159 @@ uint32_t SStrPack(char* dest, const char* source, uint32_t destsize) {
|
|||
return static_cast<uint32_t>(i - dest);
|
||||
}
|
||||
|
||||
size_t SStrPrintf(char* dest, size_t maxchars, const char* format, ...) {
|
||||
size_t STORMCDECL SStrPrintf(char* dest, size_t maxchars, const char* format, ...) {
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
|
||||
STORM_ASSERT(dest);
|
||||
STORM_ASSERT(format);
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(dest);
|
||||
STORM_VALIDATE(format);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
return ISStrVPrintf(format, va, dest, maxchars);
|
||||
return ISStrVPrintf(dest, maxchars, format, va);
|
||||
}
|
||||
|
||||
const char* SStrStr(const char* string, const char* search) {
|
||||
STORM_ASSERT(string);
|
||||
STORM_ASSERT(search);
|
||||
size_t STORMCDECL SStrVPrintf(char* dest, size_t maxchars, const char* format, va_list arglist) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(dest);
|
||||
STORM_VALIDATE(format);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
if (!*string) {
|
||||
return nullptr;
|
||||
}
|
||||
return ISStrVPrintf(dest, maxchars, format, arglist);
|
||||
}
|
||||
|
||||
auto searchEnd = search;
|
||||
while (*searchEnd) {
|
||||
searchEnd++;
|
||||
}
|
||||
size_t searchLength = searchEnd - search;
|
||||
char* STORMAPI SStrStr(char* string, const char* search) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE(search);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
auto substring = string;
|
||||
size_t searchLength = SStrLen(search);
|
||||
|
||||
while (SStrCmp(substring, search, searchLength)) {
|
||||
substring++;
|
||||
|
||||
if (!*substring) {
|
||||
return nullptr;
|
||||
for (; *string; string++) {
|
||||
if (!SStrCmp(string, search, searchLength)) {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
|
||||
return substring;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SStrTokenize(const char** string, char* buffer, size_t bufferchars, const char* whitespace, int32_t* quoted) {
|
||||
const char* STORMAPI SStrStr(const char* string, const char* search) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE(search);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
size_t searchLength = SStrLen(search);
|
||||
|
||||
for (; *string; string++) {
|
||||
if (!SStrCmp(string, search, searchLength)) {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char* STORMAPI SStrStrI(char* string, const char* search) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE(search);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
size_t searchLength = SStrLen(search);
|
||||
|
||||
for (; *string; string++) {
|
||||
if (!SStrCmpI(string, search, searchLength)) {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* STORMAPI SStrStrI(const char* string, const char* search) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE(search);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
size_t searchLength = SStrLen(search);
|
||||
|
||||
for (; *string; string++) {
|
||||
if (!SStrCmpI(string, search, searchLength)) {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void STORMAPI SStrTokenize(const char** string, char* buffer, size_t bufferchars, const char* whitespace, int32_t* quoted) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE(*string);
|
||||
STORM_VALIDATE(buffer || !bufferchars);
|
||||
STORM_VALIDATE(buffer || bufferchars == 0);
|
||||
STORM_VALIDATE(whitespace);
|
||||
STORM_VALIDATE_END_VOID;
|
||||
|
||||
int32_t checkquotes = SStrChr(whitespace, '"') != nullptr;
|
||||
|
||||
int32_t inquotes = 0;
|
||||
int32_t usedquotes = 0;
|
||||
auto curstring = *string;
|
||||
const char* currsource = *string;
|
||||
|
||||
auto v17 = false;
|
||||
for (const char* w = whitespace; w && *w; w++) {
|
||||
if (*w == '"') {
|
||||
v17 = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (*curstring && SStrChr(whitespace, *curstring)) {
|
||||
if (v17 && *curstring == '"') {
|
||||
inquotes = 1;
|
||||
while (*currsource && SStrChr(whitespace, *currsource)) {
|
||||
if (checkquotes && *currsource == '"') {
|
||||
usedquotes = 1;
|
||||
curstring++;
|
||||
inquotes = 1;
|
||||
currsource++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
curstring++;
|
||||
currsource++;
|
||||
}
|
||||
|
||||
uint32_t bufferlen = 0;
|
||||
uint32_t destchars = 0;
|
||||
|
||||
if (*curstring) {
|
||||
auto curbuffer = buffer;
|
||||
|
||||
while (v17 && *curstring == '"') {
|
||||
if (bufferlen && !inquotes) {
|
||||
goto LABEL_35;
|
||||
while(*currsource) {
|
||||
if (checkquotes && *currsource == '"') {
|
||||
if (destchars && !inquotes) {
|
||||
break;
|
||||
}
|
||||
|
||||
curstring++;
|
||||
usedquotes = 1;
|
||||
inquotes = inquotes == 0;
|
||||
inquotes = !inquotes;
|
||||
currsource++;
|
||||
|
||||
if (!inquotes) {
|
||||
goto LABEL_35;
|
||||
}
|
||||
LABEL_32:
|
||||
if (!*curstring) {
|
||||
goto LABEL_35;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inquotes) {
|
||||
LABEL_29:
|
||||
if (curbuffer - buffer < bufferchars) {
|
||||
bufferlen++;
|
||||
*curbuffer = *curstring;
|
||||
curbuffer++;
|
||||
else {
|
||||
if (!inquotes && SStrChr(whitespace, *currsource)) {
|
||||
currsource++;
|
||||
break;
|
||||
}
|
||||
|
||||
curstring++;
|
||||
|
||||
goto LABEL_32;
|
||||
if (destchars + 1 < bufferchars) {
|
||||
buffer[destchars] = *currsource;
|
||||
destchars++;
|
||||
}
|
||||
currsource++;
|
||||
}
|
||||
|
||||
auto v14 = SStrChr(whitespace, *curstring);
|
||||
|
||||
if (!v14) {
|
||||
goto LABEL_29;
|
||||
}
|
||||
|
||||
curstring++;
|
||||
}
|
||||
|
||||
LABEL_35:
|
||||
if (bufferlen < bufferchars) {
|
||||
buffer[bufferlen] = 0;
|
||||
if (destchars < bufferchars) {
|
||||
buffer[destchars] = 0;
|
||||
}
|
||||
|
||||
*string = curstring;
|
||||
*string = currsource;
|
||||
|
||||
if (quoted) {
|
||||
*quoted = usedquotes;
|
||||
}
|
||||
}
|
||||
|
||||
float SStrToFloat(const char* string) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
static inline double ISStrToDouble(const char* string) {
|
||||
SStrInitialize();
|
||||
|
||||
double result;
|
||||
|
|
@ -630,6 +763,7 @@ float SStrToFloat(const char* string) {
|
|||
int32_t v24 = 0;
|
||||
|
||||
if (v23 < 10) {
|
||||
int32_t v25 = 0;
|
||||
int32_t v26 = -1;
|
||||
double v31;
|
||||
|
||||
|
|
@ -637,7 +771,7 @@ float SStrToFloat(const char* string) {
|
|||
string++;
|
||||
|
||||
if (v24 < 20) {
|
||||
v31 = s_realDigit[v24][v23];
|
||||
v31 = s_realDigit[0][v25 + v23];
|
||||
} else {
|
||||
v31 = pow(v16, v26) * v23;
|
||||
}
|
||||
|
|
@ -647,6 +781,7 @@ float SStrToFloat(const char* string) {
|
|||
v23 = *string - '0';
|
||||
v24++;
|
||||
v26--;
|
||||
v25 += 10;
|
||||
} while (v23 < 10);
|
||||
}
|
||||
}
|
||||
|
|
@ -665,10 +800,26 @@ float SStrToFloat(const char* string) {
|
|||
result = -result;
|
||||
}
|
||||
|
||||
return static_cast<float>(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t SStrToInt(const char* string) {
|
||||
double STORMAPI SStrToDouble(const char* string) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
return ISStrToDouble(string);
|
||||
}
|
||||
|
||||
float STORMAPI SStrToFloat(const char* string) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
return static_cast<float>(ISStrToDouble(string));
|
||||
}
|
||||
|
||||
int32_t STORMAPI SStrToInt(const char* string) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
|
@ -694,7 +845,7 @@ int32_t SStrToInt(const char* string) {
|
|||
return result;
|
||||
}
|
||||
|
||||
uint32_t SStrToUnsigned(const char* string) {
|
||||
uint32_t STORMAPI SStrToUnsigned(const char* string) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
|
@ -710,7 +861,7 @@ uint32_t SStrToUnsigned(const char* string) {
|
|||
return result;
|
||||
}
|
||||
|
||||
void SStrUpper(char* string) {
|
||||
void STORMAPI SStrUpper(char* string) {
|
||||
while (*string) {
|
||||
*string = static_cast<char>(toupper(*string));
|
||||
string++;
|
||||
|
|
|
|||
|
|
@ -1,50 +1,69 @@
|
|||
#ifndef STORM_STRING_HPP
|
||||
#define STORM_STRING_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdarg>
|
||||
#include <cstdlib>
|
||||
#include "Core.hpp"
|
||||
|
||||
#define STORM_MAX_PATH 260
|
||||
#define STORM_MAX_STR 0x7FFFFFFF
|
||||
|
||||
char* SStrChr(char* string, char search);
|
||||
#define SSTR_HASH_CASESENSITIVE 1
|
||||
|
||||
const char* SStrChr(const char* string, char search);
|
||||
char* STORMAPI SStrChr(char* string, char search);
|
||||
|
||||
char* SStrChrR(char* string, char search);
|
||||
const char* STORMAPI SStrChr(const char* string, char search);
|
||||
|
||||
const char* SStrChrR(const char* string, char search);
|
||||
const char* STORMAPI SStrChrBidir(const char* string, char search, int32_t reverse);
|
||||
|
||||
int32_t SStrCmp(const char* string1, const char* string2, size_t maxchars);
|
||||
char* STORMAPI SStrChrR(char* string, char search);
|
||||
|
||||
int32_t SStrCmpI(const char* string1, const char* string2, size_t maxchars);
|
||||
const char* STORMAPI SStrChrR(const char* string, char search);
|
||||
|
||||
size_t SStrCopy(char* dest, const char* source, size_t destsize);
|
||||
int32_t STORMAPI SStrCmp(const char* string1, const char* string2, size_t maxchars = STORM_MAX_STR);
|
||||
|
||||
size_t SStrNCopy(char* dest, const char* source, size_t maxchars, size_t destsize);
|
||||
int32_t STORMAPI SStrCmpI(const char* string1, const char* string2, size_t maxchars = STORM_MAX_STR);
|
||||
|
||||
char* SStrDupA(const char* string, const char* filename, uint32_t linenumber);
|
||||
size_t STORMAPI SStrCopy(char* dest, const char* source, size_t destsize = STORM_MAX_STR);
|
||||
|
||||
uint32_t SStrHashHT(const char* string);
|
||||
void STORMAPI SStrDestroy();
|
||||
|
||||
size_t SStrLen(const char* string);
|
||||
char* STORMAPI SStrDupA(const char* string, const char* filename, uint32_t linenumber);
|
||||
|
||||
void SStrLower(char* string);
|
||||
uint32_t STORMAPI SStrHash(const char* string, uint32_t flags = 0, uint32_t seed = 0);
|
||||
|
||||
uint32_t SStrPack(char* dest, const char* source, uint32_t destsize);
|
||||
uint32_t STORMAPI SStrHashHT(const char* string);
|
||||
|
||||
size_t SStrPrintf(char* dest, size_t maxchars, const char* format, ...);
|
||||
int64_t STORMAPI SStrHash64(const char* string, uint32_t flags = 0, int64_t seed = 0);
|
||||
|
||||
const char* SStrStr(const char* string, const char* search);
|
||||
size_t STORMAPI SStrLen(const char* string);
|
||||
|
||||
void SStrTokenize(const char** string, char* buffer, size_t bufferchars, const char* whitespace, int32_t* quoted);
|
||||
void STORMAPI SStrLower(char* string);
|
||||
|
||||
float SStrToFloat(const char* string);
|
||||
uint32_t STORMAPI SStrPack(char* dest, const char* source, uint32_t destsize);
|
||||
|
||||
int32_t SStrToInt(const char* string);
|
||||
size_t STORMCDECL SStrPrintf(char* dest, size_t maxchars, const char* format, ...);
|
||||
|
||||
uint32_t SStrToUnsigned(const char* string);
|
||||
size_t STORMCDECL SStrVPrintf(char* dest, size_t maxchars, const char* format, va_list arglist);
|
||||
|
||||
void SStrUpper(char* string);
|
||||
char* STORMAPI SStrStr(char* string, const char* search);
|
||||
|
||||
const char* STORMAPI SStrStr(const char* string, const char* search);
|
||||
|
||||
char* STORMAPI SStrStrI(char* string, const char* search);
|
||||
|
||||
const char* STORMAPI SStrStrI(const char* string, const char* search);
|
||||
|
||||
void STORMAPI SStrTokenize(const char** string, char* buffer, size_t bufferchars, const char* whitespace, int32_t* quoted);
|
||||
|
||||
double STORMAPI SStrToDouble(const char* string);
|
||||
|
||||
float STORMAPI SStrToFloat(const char* string);
|
||||
|
||||
int32_t STORMAPI SStrToInt(const char* string);
|
||||
|
||||
uint32_t STORMAPI SStrToUnsigned(const char* string);
|
||||
|
||||
void STORMAPI SStrUpper(char* string);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
804
storm/Transparency.cpp
Normal file
804
storm/Transparency.cpp
Normal file
|
|
@ -0,0 +1,804 @@
|
|||
#include "storm/Transparency.hpp"
|
||||
#include "storm/List.hpp"
|
||||
#include "storm/Error.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
|
||||
#define COPY 0
|
||||
#define SKIP 1
|
||||
#define NUM_OPS 2
|
||||
|
||||
#define MAXSPANLENGTH 0xFC
|
||||
#define TRANS_CHUNKSIZE 4096
|
||||
|
||||
struct TRANS : TSLinkedNode<TRANS> {
|
||||
uint8_t* data;
|
||||
uint32_t dataalloc;
|
||||
uint32_t databytes;
|
||||
uint32_t instructionoffset;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
RECT boundrect;
|
||||
};
|
||||
|
||||
// Replacing windows struct
|
||||
struct WHOA_SIZE {
|
||||
int32_t cx, cy;
|
||||
};
|
||||
|
||||
struct BUFFER {
|
||||
uint8_t* data;
|
||||
uint32_t bytesalloc;
|
||||
uint32_t bytesused;
|
||||
uint32_t chunksize;
|
||||
};
|
||||
|
||||
// Defaults from SC 1.17's storm.dll
|
||||
WHOA_SIZE s_dirtysize = { 40, 30 };
|
||||
int32_t s_dirtyxshift = 4;
|
||||
int32_t s_dirtyxsize = 16;
|
||||
int32_t s_dirtyyshift = 4;
|
||||
int32_t s_dirtyysize = 16;
|
||||
|
||||
uint32_t* s_dirtyoffset;
|
||||
uint8_t* s_savedata;
|
||||
uint32_t s_savedataalloc;
|
||||
STORM_LIST(TRANS) s_translist;
|
||||
|
||||
void BufferCreate(BUFFER* buffer) {
|
||||
buffer->chunksize = TRANS_CHUNKSIZE;
|
||||
buffer->bytesused = 0;
|
||||
if (s_savedata) {
|
||||
buffer->data = s_savedata;
|
||||
buffer->bytesalloc = s_savedataalloc;
|
||||
s_savedata = nullptr;
|
||||
s_savedataalloc = 0;
|
||||
}
|
||||
else {
|
||||
buffer->bytesalloc = TRANS_CHUNKSIZE;
|
||||
buffer->data = static_cast<uint8_t*>(STORM_ALLOC(buffer->bytesalloc));
|
||||
}
|
||||
}
|
||||
|
||||
void BufferReserve(BUFFER* buffer, uint32_t bytes, uint8_t** adjptr1, uint8_t** adjptr2) {
|
||||
uint32_t newalloc = buffer->bytesalloc;
|
||||
while (newalloc < bytes + buffer->bytesused) {
|
||||
newalloc += buffer->chunksize;
|
||||
}
|
||||
|
||||
if (newalloc != buffer->bytesalloc) {
|
||||
uint8_t* newdata = static_cast<uint8_t*>(STORM_ALLOC(newalloc));
|
||||
SMemCopy(newdata, buffer->data, buffer->bytesused);
|
||||
STORM_FREE(buffer->data);
|
||||
|
||||
if (adjptr1 && *adjptr1) {
|
||||
*adjptr1 = &newdata[*adjptr1 - buffer->data];
|
||||
}
|
||||
if (adjptr2 && *adjptr2) {
|
||||
*adjptr2 = &newdata[*adjptr2 - buffer->data];
|
||||
}
|
||||
buffer->bytesalloc = newalloc;
|
||||
buffer->data = newdata;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertBitmapToTransparency(uint8_t* bits, int32_t width, int32_t height, int32_t bitdepth, RECT* rect, RECT* boundrect, uint8_t colorkey, int32_t maskonly, uint8_t* data, uint32_t* databytes, uint32_t* instructionoffset) {
|
||||
uint32_t size = 0;
|
||||
int32_t start = rect ? rect->left + width * rect->top : 0;
|
||||
int32_t cx = rect ? rect->right - rect->left : width;
|
||||
int32_t cy = rect ? rect->bottom - rect->top : height;
|
||||
|
||||
int32_t adjust = width - cx;
|
||||
|
||||
*boundrect = { INT_MAX, INT_MAX, 0, 0 };
|
||||
|
||||
if (!maskonly) {
|
||||
uint8_t* source = &bits[start];
|
||||
for (int32_t y = 0; y < cy; y++) {
|
||||
bool found = false;
|
||||
for (int32_t x = 0; x < cx; x++) {
|
||||
if (*source != colorkey) {
|
||||
size++;
|
||||
if (data) *data++ = *source;
|
||||
|
||||
if (x < boundrect->left) boundrect->left = x;
|
||||
if (x >= boundrect->right) boundrect->right = x + 1;
|
||||
found = true;
|
||||
}
|
||||
source++;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if (y < boundrect->top) boundrect->top = y;
|
||||
if (y >= boundrect->bottom) boundrect->bottom = y + 1;
|
||||
}
|
||||
|
||||
source += adjust;
|
||||
}
|
||||
}
|
||||
|
||||
if (boundrect->left > boundrect->right) boundrect->left = boundrect->right;
|
||||
if (boundrect->top > boundrect->bottom) boundrect->top = boundrect->bottom;
|
||||
|
||||
if (size % 4 != 0) {
|
||||
if (data) data += 4 - (size % 4);
|
||||
size += 4 - (size % 4);
|
||||
}
|
||||
|
||||
if (instructionoffset) *instructionoffset = size;
|
||||
|
||||
uint8_t* source = &bits[start];
|
||||
while (cy--) {
|
||||
uint8_t copybytes = 0;
|
||||
uint8_t skipbytes = 0;
|
||||
bool copymode = true;
|
||||
|
||||
for (int32_t x = cx; x--;) {
|
||||
bool output = false;
|
||||
bool expectedcopymode = *source++ != colorkey;
|
||||
if (expectedcopymode == copymode) {
|
||||
if (copymode) {
|
||||
copybytes++;
|
||||
}
|
||||
else {
|
||||
skipbytes++;
|
||||
}
|
||||
}
|
||||
else if (copymode) {
|
||||
copymode = false;
|
||||
skipbytes++;
|
||||
}
|
||||
else {
|
||||
output = true;
|
||||
source--;
|
||||
x++;
|
||||
}
|
||||
|
||||
if (output || copybytes == MAXSPANLENGTH || skipbytes == MAXSPANLENGTH || x == 0) {
|
||||
size += 2;
|
||||
if (data) {
|
||||
*data++ = copybytes;
|
||||
*data++ = skipbytes;
|
||||
}
|
||||
copybytes = 0;
|
||||
skipbytes = 0;
|
||||
copymode = true;
|
||||
}
|
||||
}
|
||||
|
||||
size += 2;
|
||||
if (data) {
|
||||
*data++ = 0;
|
||||
*data++ = 0;
|
||||
}
|
||||
|
||||
source += adjust;
|
||||
}
|
||||
|
||||
if (databytes) *databytes = size;
|
||||
}
|
||||
|
||||
int32_t ConvertColorRefToColorData(uint32_t colorref) {
|
||||
if (colorref & STRANS_COLORKEY_VALID) {
|
||||
return colorref & STRANS_COLORKEY_MASK;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
HSTRANS CreateTransparencyRecord(HSTRANS baseptr) {
|
||||
HSTRANS transptr = s_translist.NewNode(STORM_LIST_TAIL, 0, 0);
|
||||
if (baseptr) {
|
||||
transptr->dataalloc = baseptr->dataalloc;
|
||||
transptr->databytes = baseptr->databytes;
|
||||
transptr->instructionoffset = baseptr->instructionoffset;
|
||||
transptr->width = baseptr->width;
|
||||
transptr->height = baseptr->height;
|
||||
transptr->boundrect = baseptr->boundrect;
|
||||
}
|
||||
return transptr;
|
||||
}
|
||||
|
||||
int32_t DetermineShift(int32_t value, int32_t* shift) {
|
||||
int32_t bits = 0, curr = 1;
|
||||
while (curr < value) {
|
||||
bits++;
|
||||
curr <<= 1;
|
||||
}
|
||||
|
||||
*shift = bits;
|
||||
return curr == value;
|
||||
}
|
||||
|
||||
int32_t InternalCreateTransparency(uint8_t* bits, int32_t width, int32_t height, int32_t bitdepth, RECT* rect, uint32_t colorkey, int32_t maskonly, HSTRANS* handle) {
|
||||
if (bitdepth != 8) return 0;
|
||||
|
||||
uint8_t paletteindex = ConvertColorRefToColorData(colorkey);
|
||||
uint32_t transbytes = 0;
|
||||
uint32_t instructionoffset = 0;
|
||||
RECT boundrect;
|
||||
|
||||
ConvertBitmapToTransparency(bits, width, height, bitdepth, rect, &boundrect, paletteindex, maskonly, nullptr, &transbytes, &instructionoffset);
|
||||
|
||||
uint8_t* transdata = static_cast<uint8_t*>(STORM_ALLOC(transbytes));
|
||||
ConvertBitmapToTransparency(bits, width, height, bitdepth, rect, &boundrect, paletteindex, maskonly, transdata, nullptr, nullptr);
|
||||
|
||||
HSTRANS newptr = CreateTransparencyRecord(nullptr);
|
||||
newptr->boundrect = boundrect;
|
||||
newptr->data = transdata;
|
||||
newptr->dataalloc = transbytes;
|
||||
newptr->databytes = transbytes;
|
||||
newptr->instructionoffset = instructionoffset;
|
||||
newptr->width = rect ? rect->right - rect->left : width;
|
||||
newptr->height = rect ? rect->bottom - rect->top : height;
|
||||
|
||||
*handle = newptr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void InternalDrawTransparency(HSTRANS trans, uint8_t* dest, int32_t destadjust) {
|
||||
uint8_t* sourceinst = &trans->data[trans->instructionoffset];
|
||||
uint8_t* sourcedata = trans->data;
|
||||
int32_t cy = trans->height;
|
||||
while (cy--) {
|
||||
uint8_t copybytes = *sourceinst++;
|
||||
uint8_t skipbytes = *sourceinst++;
|
||||
while (copybytes || skipbytes) {
|
||||
while(copybytes) {
|
||||
*dest++ = *sourcedata++;
|
||||
copybytes--;
|
||||
}
|
||||
dest += skipbytes;
|
||||
|
||||
copybytes = *sourceinst++;
|
||||
skipbytes = *sourceinst++;
|
||||
}
|
||||
dest += destadjust;
|
||||
}
|
||||
}
|
||||
|
||||
void InternalDrawTransparencyFromSource(HSTRANS trans, uint8_t* dest, uint8_t* source, int32_t destadjust, int32_t sourceadjust) {
|
||||
uint8_t* sourceinst = &trans->data[trans->instructionoffset];
|
||||
for (int32_t y = 0; y < trans->height; y++) {
|
||||
uint8_t copybytes = *(sourceinst++);
|
||||
uint8_t skipbytes = *(sourceinst++);
|
||||
while (copybytes || skipbytes) {
|
||||
std::memcpy(dest, source, copybytes);
|
||||
source += copybytes;
|
||||
dest += copybytes;
|
||||
|
||||
dest += skipbytes;
|
||||
source += skipbytes;
|
||||
|
||||
copybytes = *(sourceinst++);
|
||||
skipbytes = *(sourceinst++);
|
||||
}
|
||||
dest += destadjust;
|
||||
source += sourceadjust;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransBlt(uint8_t* dest, int32_t destx, int32_t desty, int32_t destpitch, HSTRANS transparency) {
|
||||
STORM_ASSERT(dest);
|
||||
STORM_ASSERT(destpitch > 0);
|
||||
STORM_ASSERT(transparency);
|
||||
STORM_ASSERT(transparency->instructionoffset);
|
||||
|
||||
InternalDrawTransparency(transparency, &dest[destpitch * desty + destx], destpitch - transparency->width);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransBltUsingMask(uint8_t* dest, uint8_t* source, int32_t destpitch, int32_t sourcepitch, HSTRANS mask) {
|
||||
STORM_ASSERT(dest);
|
||||
STORM_ASSERT(source);
|
||||
STORM_ASSERT(destpitch > 0);
|
||||
STORM_ASSERT(mask);
|
||||
|
||||
int32_t sourceadjust = sourcepitch ? sourcepitch - mask->width : 0;
|
||||
int32_t destadjust = destpitch - mask->width;
|
||||
InternalDrawTransparencyFromSource(mask, dest, source, destadjust, sourceadjust);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransCombineMasks(HSTRANS basemask, HSTRANS secondmask, int32_t offsetx, int32_t offsety, uint32_t flags, HSTRANS* handle) {
|
||||
if (handle) *handle = nullptr;
|
||||
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(basemask);
|
||||
STORM_VALIDATE(secondmask);
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
bool intersect = (flags & STRANS_CF_INTERSECT) != 0;
|
||||
bool invertsecond = (flags & STRANS_CF_INVERTSECOND) != 0;
|
||||
|
||||
bool usespan[NUM_OPS][NUM_OPS][NUM_OPS];
|
||||
for (int32_t spantype0 = 0; spantype0 < NUM_OPS; spantype0++) {
|
||||
for (int32_t spantypedest = 0; spantypedest < NUM_OPS; spantypedest++) {
|
||||
if (intersect) {
|
||||
usespan[spantype0][spantypedest][invertsecond ? SKIP : COPY] = (spantype0 == spantypedest);
|
||||
usespan[spantype0][spantypedest][invertsecond ? COPY : SKIP] = (spantypedest == SKIP);
|
||||
}
|
||||
else {
|
||||
usespan[spantype0][spantypedest][invertsecond ? SKIP : COPY] = (spantypedest == COPY);
|
||||
usespan[spantype0][spantypedest][invertsecond ? COPY : SKIP] = (spantype0 == spantypedest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* baseptr = &basemask->data[basemask->instructionoffset];
|
||||
uint8_t* secondptr = &secondmask->data[secondmask->instructionoffset];
|
||||
|
||||
uint8_t copybytes, skipbytes;
|
||||
|
||||
for (int32_t i = offsety; i < 0; i++) {
|
||||
do {
|
||||
copybytes = *secondptr++;
|
||||
skipbytes = *secondptr++;
|
||||
} while (copybytes || skipbytes);
|
||||
}
|
||||
|
||||
BUFFER buffer;
|
||||
BufferCreate(&buffer);
|
||||
uint8_t* dest = buffer.data;
|
||||
for (int32_t line = 0; line < basemask->height; line++) {
|
||||
BufferReserve(&buffer, 2 * (basemask->width + 1), &dest, nullptr);
|
||||
|
||||
if (line >= offsety && line <= offsety + secondmask->height - 1) {
|
||||
int32_t span[2][NUM_OPS] = {};
|
||||
span[1][SKIP] = std::max(0, offsetx);
|
||||
bool hitend = false;
|
||||
|
||||
if (offsetx < 0) {
|
||||
int32_t bytesleft = -offsetx;
|
||||
while (bytesleft) {
|
||||
span[1][COPY] = *secondptr++;
|
||||
span[1][SKIP] = *secondptr++;
|
||||
|
||||
if (span[1][COPY] == 0 && span[1][SKIP] == 0) {
|
||||
span[1][SKIP] = INT_MAX;
|
||||
hitend = true;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int32_t adjustremaining = 0; adjustremaining < NUM_OPS; adjustremaining++) {
|
||||
int32_t adjustment = std::min(bytesleft, span[1][adjustremaining]);
|
||||
span[1][adjustremaining] -= adjustment;
|
||||
bytesleft -= adjustment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while(1) {
|
||||
span[0][COPY] = *baseptr++;
|
||||
span[0][SKIP] = *baseptr++;
|
||||
if (span[0][COPY] == 0 && span[0][SKIP] == 0) break;
|
||||
|
||||
for (int32_t j = 0; j < NUM_OPS; j++) {
|
||||
while(span[0][j]) {
|
||||
if (span[1][COPY] == 0 && span[1][SKIP] == 0) {
|
||||
span[1][COPY] = *secondptr++;
|
||||
span[1][SKIP] = *secondptr++;
|
||||
if (span[1][COPY] == 0 && span[1][SKIP] == 0) {
|
||||
span[1][SKIP] = INT_MAX;
|
||||
hitend = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t inst[NUM_OPS];
|
||||
for (int32_t k = 0; k < NUM_OPS; k++) {
|
||||
int32_t spanlength = 0;
|
||||
if (usespan[j][k][COPY]) {
|
||||
spanlength = span[1][COPY];
|
||||
}
|
||||
|
||||
if (usespan[j][k][SKIP] && (usespan[j][k][COPY] || !span[1][COPY])) {
|
||||
spanlength += span[1][SKIP];
|
||||
}
|
||||
|
||||
spanlength = std::min(span[0][j], spanlength);
|
||||
inst[k] = spanlength;
|
||||
span[0][j] -= spanlength;
|
||||
for (int32_t m = 0; m < NUM_OPS; m++) {
|
||||
int32_t v11 = std::min(span[1][m], spanlength);
|
||||
span[1][m] -= v11;
|
||||
spanlength -= v11;
|
||||
}
|
||||
}
|
||||
|
||||
if (inst[COPY] || inst[SKIP]) {
|
||||
*dest++ = inst[COPY];
|
||||
*dest++ = inst[SKIP];
|
||||
buffer.bytesused += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*dest++ = 0;
|
||||
*dest++ = 0;
|
||||
buffer.bytesused += 2;
|
||||
|
||||
if (!hitend) {
|
||||
do {
|
||||
copybytes = *secondptr++;
|
||||
skipbytes = *secondptr++;
|
||||
} while (copybytes || skipbytes);
|
||||
}
|
||||
}
|
||||
else if (intersect == invertsecond) {
|
||||
do {
|
||||
buffer.bytesused += 2;
|
||||
copybytes = *baseptr++;
|
||||
skipbytes = *baseptr++;
|
||||
|
||||
*dest++ = copybytes;
|
||||
*dest++ = skipbytes;
|
||||
} while (copybytes || skipbytes);
|
||||
}
|
||||
else {
|
||||
int32_t width = basemask->width;
|
||||
while (width) {
|
||||
int32_t skipspan = std::min(width, MAXSPANLENGTH);
|
||||
*dest++ = 0;
|
||||
*dest++ = skipspan;
|
||||
buffer.bytesused += 2;
|
||||
|
||||
width -= skipspan;
|
||||
}
|
||||
*dest++ = 0;
|
||||
*dest++ = 0;
|
||||
buffer.bytesused += 2;
|
||||
|
||||
do {
|
||||
copybytes = *baseptr++;
|
||||
skipbytes = *baseptr++;
|
||||
} while (copybytes || skipbytes);
|
||||
}
|
||||
}
|
||||
|
||||
HSTRANS newptr = CreateTransparencyRecord(basemask);
|
||||
newptr->data = buffer.data;
|
||||
newptr->dataalloc = buffer.bytesalloc;
|
||||
newptr->databytes = buffer.bytesused;
|
||||
newptr->instructionoffset = 0;
|
||||
*handle = newptr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransCreateE(uint8_t* bits, int32_t width, int32_t height, int32_t bitdepth, RECT* rect, uint32_t colorkey, HSTRANS* handle) {
|
||||
if (handle) *handle = nullptr;
|
||||
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(bits);
|
||||
STORM_VALIDATE(width);
|
||||
STORM_VALIDATE(height);
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
return InternalCreateTransparency(bits, width, height, bitdepth, rect, colorkey, 0, handle);
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransCreateI(uint8_t* bits, int32_t width, int32_t height, int32_t bitdepth, RECT* rect, uint32_t colorkey, HSTRANS* handle) {
|
||||
RECT exclrect;
|
||||
RECT* exclrectptr = rect;
|
||||
if (rect) {
|
||||
exclrect = { rect->left, rect->top, rect->right + 1, rect->bottom + 1 };
|
||||
exclrectptr = &exclrect;
|
||||
}
|
||||
return STransCreateE(bits, width, height, bitdepth, exclrectptr, colorkey, handle);
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransCreateMaskE(uint8_t* bits, int32_t width, int32_t height, int32_t bitdepth, RECT* rect, uint32_t colorkey, HSTRANS* handle) {
|
||||
if (handle) *handle = nullptr;
|
||||
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(bits);
|
||||
STORM_VALIDATE(width);
|
||||
STORM_VALIDATE(height);
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
return InternalCreateTransparency(bits, width, height, bitdepth, rect, colorkey, 1, handle);
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransCreateMaskI(uint8_t* bits, int32_t width, int32_t height, int32_t bitdepth, RECT* rect, uint32_t colorkey, HSTRANS* handle) {
|
||||
RECT exclrect;
|
||||
RECT* exclrectptr = rect;
|
||||
if (rect) {
|
||||
exclrect = { rect->left, rect->top, rect->right + 1, rect->bottom + 1 };
|
||||
exclrectptr = &exclrect;
|
||||
}
|
||||
return STransCreateMaskE(bits, width, height, bitdepth, exclrectptr, colorkey, handle);
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransDelete(HSTRANS handle) {
|
||||
if (handle->data) {
|
||||
if (s_savedata) {
|
||||
STORM_FREE(s_savedata);
|
||||
}
|
||||
|
||||
s_savedata = handle->data;
|
||||
s_savedataalloc = handle->dataalloc;
|
||||
|
||||
handle->data = nullptr;
|
||||
handle->dataalloc = 0;
|
||||
}
|
||||
|
||||
s_translist.DeleteNode(handle);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransDestroy() {
|
||||
while (TRANS* curr = s_translist.Head()) {
|
||||
//SErrReportResourceLeak("HSTRANS");
|
||||
STransDelete(curr);
|
||||
}
|
||||
|
||||
if (s_dirtyoffset) {
|
||||
STORM_FREE(s_dirtyoffset);
|
||||
s_dirtyoffset = nullptr;
|
||||
}
|
||||
|
||||
if (s_savedata) {
|
||||
STORM_FREE(s_savedata);
|
||||
s_savedata = nullptr;
|
||||
s_savedataalloc = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransDuplicate(HSTRANS source, HSTRANS* handle) {
|
||||
if (handle) *handle = nullptr;
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(source);
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
uint8_t* data = static_cast<uint8_t*>(STORM_ALLOC(source->dataalloc));
|
||||
SMemCopy(data, source->data, source->databytes);
|
||||
|
||||
HSTRANS newtrans = CreateTransparencyRecord(source);
|
||||
newtrans->data = data;
|
||||
|
||||
*handle = newtrans;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransIntersectDirtyArray(HSTRANS sourcemask, uint8_t* dirtyarray, uint8_t dirtyarraymask, HSTRANS* handle) {
|
||||
if (handle) *handle = nullptr;
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(sourcemask);
|
||||
STORM_VALIDATE(dirtyarray);
|
||||
STORM_VALIDATE(dirtyarraymask);
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
if (s_dirtyoffset == 0) return 0;
|
||||
|
||||
BUFFER buffer;
|
||||
BufferCreate(&buffer);
|
||||
|
||||
uint8_t* source = &sourcemask->data[sourcemask->instructionoffset];
|
||||
uint8_t* dest = buffer.data;
|
||||
uint8_t* lastsource = source;
|
||||
uint8_t* lastdest = dest;
|
||||
|
||||
for (int32_t y = 0; y < sourcemask->height; y++) {
|
||||
BufferReserve(&buffer, 2 * (sourcemask->width + 1), &dest, &lastdest);
|
||||
|
||||
// wtf?
|
||||
if (((s_dirtyysize - 1) & y) != 0 && !memcmp(source, lastsource, source - lastsource)) {
|
||||
ptrdiff_t sourcebytes = source - lastsource;
|
||||
ptrdiff_t destbytes = dest - lastdest;
|
||||
memcpy(dest, lastdest, dest - lastdest);
|
||||
|
||||
lastsource = source;
|
||||
lastdest = dest;
|
||||
source += sourcebytes;
|
||||
dest += destbytes;
|
||||
buffer.bytesused += static_cast<uint32_t>(destbytes);
|
||||
}
|
||||
else {
|
||||
uint8_t copybytes, skipbytes;
|
||||
|
||||
lastsource = source;
|
||||
lastdest = dest;
|
||||
uint8_t* dirty = &dirtyarray[s_dirtyoffset[y >> s_dirtyyshift]];
|
||||
uint32_t xoffset = 0;
|
||||
do {
|
||||
copybytes = *source++;
|
||||
skipbytes = *source++;
|
||||
|
||||
if (copybytes) {
|
||||
uint8_t bytesleft = copybytes;
|
||||
uint8_t length = 0;
|
||||
bool copymode = true;
|
||||
|
||||
while (bytesleft != 0 || length != 0) {
|
||||
if (bytesleft != 0 && ((dirtyarraymask & *dirty) != 0) == copymode) {
|
||||
uint8_t cellleft = s_dirtyxsize - xoffset;
|
||||
if (bytesleft >= cellleft) {
|
||||
length += cellleft;
|
||||
bytesleft -= cellleft;
|
||||
xoffset = 0;
|
||||
dirty++;
|
||||
}
|
||||
else {
|
||||
length += bytesleft;
|
||||
xoffset += bytesleft;
|
||||
bytesleft = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*dest++ = length;
|
||||
buffer.bytesused++;
|
||||
length = 0;
|
||||
copymode = !copymode;
|
||||
}
|
||||
}
|
||||
|
||||
if (skipbytes || !copymode) {
|
||||
if (copymode) {
|
||||
*dest++ = 0;
|
||||
buffer.bytesused++;
|
||||
}
|
||||
*dest++ = skipbytes;
|
||||
buffer.bytesused++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*dest++ = 0;
|
||||
*dest++ = skipbytes;
|
||||
buffer.bytesused += 2;
|
||||
}
|
||||
|
||||
if (skipbytes) {
|
||||
xoffset += skipbytes;
|
||||
dirty += xoffset >> s_dirtyxshift;
|
||||
xoffset &= s_dirtyxsize - 1;
|
||||
}
|
||||
|
||||
} while (copybytes || skipbytes);
|
||||
}
|
||||
}
|
||||
|
||||
HSTRANS newptr = CreateTransparencyRecord(sourcemask);
|
||||
newptr->data = buffer.data;
|
||||
newptr->dataalloc = buffer.bytesalloc;
|
||||
newptr->databytes = buffer.bytesused;
|
||||
newptr->instructionoffset = 0;
|
||||
*handle = newptr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransInvertMask(HSTRANS sourcemask, HSTRANS* handle) {
|
||||
if (handle) *handle = nullptr;
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(sourcemask);
|
||||
STORM_VALIDATE(handle);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
uint32_t dataalloc = sourcemask->databytes - sourcemask->instructionoffset + 2 * sourcemask->height;
|
||||
uint8_t* data = static_cast<uint8_t*>(STORM_ALLOC(dataalloc));
|
||||
uint32_t bytes = 0;
|
||||
|
||||
uint8_t* source = &sourcemask->data[sourcemask->instructionoffset];
|
||||
uint8_t* dest = data;
|
||||
|
||||
for (int32_t cy = sourcemask->height; cy--;) {
|
||||
uint8_t copybytes = 0, skipbytes = 0;
|
||||
do {
|
||||
skipbytes = *source++;
|
||||
if (copybytes || skipbytes) {
|
||||
*dest++ = copybytes;
|
||||
*dest++ = skipbytes;
|
||||
bytes += 2;
|
||||
}
|
||||
copybytes = *source++;
|
||||
} while (copybytes || skipbytes);
|
||||
|
||||
*dest++ = 0;
|
||||
*dest++ = 0;
|
||||
bytes += 2;
|
||||
}
|
||||
|
||||
HSTRANS newptr = CreateTransparencyRecord(sourcemask);
|
||||
newptr->data = data;
|
||||
newptr->dataalloc = dataalloc;
|
||||
newptr->databytes = bytes;
|
||||
newptr->instructionoffset = 0;
|
||||
|
||||
*handle = newptr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransIsPixelInMask(HSTRANS mask, int32_t offsetx, int32_t offsety) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(mask);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
if (offsetx < 0 || offsety < 0 || offsetx >= mask->width || offsety >= mask->height) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t copybytes, skipbytes;
|
||||
uint8_t* instptr = &mask->data[mask->instructionoffset];
|
||||
while(offsety--) {
|
||||
do {
|
||||
copybytes = *instptr++;
|
||||
skipbytes = *instptr++;
|
||||
} while (copybytes || skipbytes);
|
||||
}
|
||||
|
||||
copybytes = *instptr++;
|
||||
skipbytes = *instptr++;
|
||||
while(copybytes || skipbytes) {
|
||||
if (copybytes > offsetx) return 1;
|
||||
offsetx -= copybytes;
|
||||
|
||||
if (skipbytes > offsetx) return 0;
|
||||
offsetx -= skipbytes;
|
||||
|
||||
copybytes = *instptr++;
|
||||
skipbytes = *instptr++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransSetDirtyArrayInfo(int32_t screencx, int32_t screency, int32_t cellcx, int32_t cellcy) {
|
||||
if (s_dirtyoffset) {
|
||||
STORM_FREE(s_dirtyoffset);
|
||||
s_dirtyoffset = nullptr;
|
||||
}
|
||||
|
||||
if (!DetermineShift(cellcx, &s_dirtyxshift)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!DetermineShift(cellcy, &s_dirtyyshift)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s_dirtysize = {
|
||||
(screencx + (1 << s_dirtyxshift) - 1) >> s_dirtyxshift,
|
||||
(screency + (1 << s_dirtyyshift) - 1) >> s_dirtyyshift,
|
||||
};
|
||||
|
||||
s_dirtyxsize = cellcx;
|
||||
s_dirtyysize = cellcy;
|
||||
|
||||
s_dirtyoffset = static_cast<uint32_t*>(STORM_ALLOC(sizeof(s_dirtyoffset[0]) * s_dirtysize.cy));
|
||||
|
||||
uint32_t offset = 0;
|
||||
for (int32_t i = 0; i < s_dirtysize.cy; i++) {
|
||||
s_dirtyoffset[i] = offset;
|
||||
offset += s_dirtysize.cx;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t STORMAPI STransUpdateDirtyArray(uint8_t* dirtyarray, uint8_t dirtyvalue, int32_t destx, int32_t desty, HSTRANS transparency, int32_t tracecontour) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(dirtyarray);
|
||||
STORM_VALIDATE(dirtyvalue);
|
||||
STORM_VALIDATE(transparency);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
if (!s_dirtyoffset) return 0;
|
||||
if (transparency->width <= 0 || transparency->height <= 0) return 0;
|
||||
if (tracecontour) return 0;
|
||||
|
||||
int32_t lastx = (transparency->boundrect.right + destx) >> s_dirtyxshift;
|
||||
int32_t lasty = (transparency->boundrect.bottom + desty) >> s_dirtyyshift;
|
||||
int32_t firstx = (transparency->boundrect.left + destx) >> s_dirtyxshift;
|
||||
int32_t firsty = (transparency->boundrect.top + desty) >> s_dirtyyshift;
|
||||
|
||||
for (int32_t y = firsty; y < lasty; y++) {
|
||||
for (int32_t x = firstx; x < lastx; x++) {
|
||||
dirtyarray[s_dirtyoffset[y] + x] |= dirtyvalue;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
51
storm/Transparency.hpp
Normal file
51
storm/Transparency.hpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef STORM_TRANSPARENCY_HPP
|
||||
#define STORM_TRANSPARENCY_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include "storm/Core.hpp"
|
||||
#include "storm/region/Types.hpp"
|
||||
|
||||
#define STRANS_CF_INTERSECT 1
|
||||
#define STRANS_CF_INVERTSECOND 2
|
||||
#define STRANS_CF_SUBTRACT 3
|
||||
|
||||
#define STRANS_COLORKEY_VALID 0x1000000
|
||||
#define STRANS_COLORKEY_MASK 0xFFFFFF
|
||||
#define STRANS_COLORKEY(x) (((x) & STRANS_COLORKEY_MASK) | STRANS_COLORKEY_VALID)
|
||||
|
||||
struct TRANS;
|
||||
typedef TRANS* HSTRANS;
|
||||
|
||||
int32_t STORMAPI STransBlt(uint8_t* dest, int32_t destx, int32_t desty, int32_t destpitch, HSTRANS transparency);
|
||||
|
||||
int32_t STORMAPI STransBltUsingMask(uint8_t* dest, uint8_t* source, int32_t destpitch, int32_t sourcepitch, HSTRANS mask);
|
||||
|
||||
int32_t STORMAPI STransCombineMasks(HSTRANS basemask, HSTRANS secondmask, int32_t offsetx, int32_t offsety, uint32_t flags, HSTRANS* handle);
|
||||
|
||||
// Exclusive rect - [left,right), [top,bottom)
|
||||
int32_t STORMAPI STransCreateE(uint8_t* bits, int32_t width, int32_t height, int32_t bitdepth, RECT* rect, uint32_t colorkey, HSTRANS* handle);
|
||||
|
||||
// Inclusive rect - [left,right], [top,bottom]
|
||||
int32_t STORMAPI STransCreateI(uint8_t* bits, int32_t width, int32_t height, int32_t bitdepth, RECT* rect, uint32_t colorkey, HSTRANS* handle);
|
||||
|
||||
int32_t STORMAPI STransCreateMaskE(uint8_t* bits, int32_t width, int32_t height, int32_t bitdepth, RECT* rect, uint32_t colorkey, HSTRANS* handle);
|
||||
|
||||
int32_t STORMAPI STransCreateMaskI(uint8_t* bits, int32_t width, int32_t height, int32_t bitdepth, RECT* rect, uint32_t colorkey, HSTRANS* handle);
|
||||
|
||||
int32_t STORMAPI STransDelete(HSTRANS handle);
|
||||
|
||||
int32_t STORMAPI STransDestroy();
|
||||
|
||||
int32_t STORMAPI STransDuplicate(HSTRANS source, HSTRANS* handle);
|
||||
|
||||
int32_t STORMAPI STransIntersectDirtyArray(HSTRANS sourcemask, uint8_t* dirtyarray, uint8_t dirtyarraymask, HSTRANS* handle);
|
||||
|
||||
int32_t STORMAPI STransInvertMask(HSTRANS sourcemask, HSTRANS* handle);
|
||||
|
||||
int32_t STORMAPI STransIsPixelInMask(HSTRANS mask, int32_t offsetx, int32_t offsety);
|
||||
|
||||
int32_t STORMAPI STransSetDirtyArrayInfo(int32_t screencx, int32_t screency, int32_t cellcx, int32_t cellcy);
|
||||
|
||||
int32_t STORMAPI STransUpdateDirtyArray(uint8_t* dirtyarray, uint8_t dirtyvalue, int32_t destx, int32_t desty, HSTRANS transparency, int32_t tracecontour = 0);
|
||||
|
||||
#endif
|
||||
|
|
@ -19,6 +19,7 @@ class TSBaseArray {
|
|||
|
||||
// Member functions
|
||||
T& operator[](uint32_t index);
|
||||
const T& operator[](uint32_t index) const;
|
||||
void CheckArrayBounds(uint32_t index) const;
|
||||
void Constructor();
|
||||
uint32_t Count() const;
|
||||
|
|
@ -33,6 +34,12 @@ T& TSBaseArray<T>::operator[](uint32_t index) {
|
|||
return this->m_data[index];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T& TSBaseArray<T>::operator[](uint32_t index) const {
|
||||
this->CheckArrayBounds(index);
|
||||
return this->m_data[index];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void TSBaseArray<T>::CheckArrayBounds(uint32_t index) const {
|
||||
if (index < this->Count()) {
|
||||
|
|
@ -40,14 +47,15 @@ void TSBaseArray<T>::CheckArrayBounds(uint32_t index) const {
|
|||
}
|
||||
|
||||
SErrDisplayErrorFmt(
|
||||
0x85100080,
|
||||
STORM_ERROR_ACCESS_OUT_OF_BOUNDS,
|
||||
this->MemFileName(),
|
||||
this->MemLineNo(),
|
||||
1,
|
||||
1,
|
||||
"index (0x%08X), array size (0x%08X)",
|
||||
index,
|
||||
this->Count());
|
||||
this->Count()
|
||||
);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@
|
|||
template <class T>
|
||||
class TSFixedArray : public TSBaseArray<T> {
|
||||
public:
|
||||
// Member functions
|
||||
TSFixedArray();
|
||||
TSFixedArray(const TSFixedArray& source);
|
||||
~TSFixedArray();
|
||||
TSFixedArray<T>& operator=(const TSFixedArray<T>& source);
|
||||
TSFixedArray& operator=(const TSFixedArray& source);
|
||||
void Clear();
|
||||
void ReallocAndClearData(uint32_t count);
|
||||
void ReallocData(uint32_t count);
|
||||
|
|
@ -23,6 +25,12 @@ TSFixedArray<T>::TSFixedArray() {
|
|||
this->Constructor();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
TSFixedArray<T>::TSFixedArray(const TSFixedArray<T>& source) {
|
||||
this->Constructor();
|
||||
this->Set(source.Count(), source.Ptr());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
TSFixedArray<T>::~TSFixedArray() {
|
||||
for (uint32_t i = 0; i < this->Count(); i++) {
|
||||
|
|
@ -41,22 +49,31 @@ TSFixedArray<T>& TSFixedArray<T>::operator=(const TSFixedArray<T>& source) {
|
|||
this->Set(source.Count(), source.Ptr());
|
||||
}
|
||||
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void TSFixedArray<T>::Clear() {
|
||||
this->~TSFixedArray<T>();
|
||||
this->Constructor();
|
||||
this->~TSFixedArray<T>();
|
||||
this->Constructor();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void TSFixedArray<T>::ReallocAndClearData(uint32_t count) {
|
||||
this->m_alloc = count;
|
||||
// Destruct existing array elements
|
||||
for (uint32_t i = 0; i < this->Count(); i++) {
|
||||
auto element = &this->operator[](i);
|
||||
element->~T();
|
||||
}
|
||||
|
||||
if (this->m_data || count) {
|
||||
void* m = SMemReAlloc(this->m_data, sizeof(T) * count, this->MemFileName(), this->MemLineNo(), 0x0);
|
||||
this->m_data = static_cast<T*>(m);
|
||||
// Reallocate if count changed
|
||||
if (count != this->m_count) {
|
||||
this->m_alloc = count;
|
||||
|
||||
if (this->m_data || count) {
|
||||
void* m = SMemReAlloc(this->m_data, sizeof(T) * count, this->MemFileName(), this->MemLineNo(), 0x0);
|
||||
this->m_data = static_cast<T*>(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,17 +6,20 @@
|
|||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
|
||||
template <class T>
|
||||
class TSGrowableArray : public TSFixedArray<T> {
|
||||
public:
|
||||
// Member variables
|
||||
uint32_t m_chunk = 0;
|
||||
|
||||
// Member functions
|
||||
uint32_t Add(uint32_t count, const T* data);
|
||||
uint32_t Add(uint32_t count, uint32_t incr, const T* data);
|
||||
uint32_t CalcChunkSize(uint32_t count);
|
||||
void GrowToFit(uint32_t index, int32_t zero);
|
||||
T* New(void);
|
||||
T* New();
|
||||
void Reserve(uint32_t count, int32_t round);
|
||||
uint32_t Reserved() const;
|
||||
uint32_t RoundToChunk(uint32_t count, uint32_t chunk);
|
||||
|
|
|
|||
|
|
@ -483,6 +483,11 @@ void ToStream(TSGrowableArray<uint8_t>& output, const BigBuffer& buffer) {
|
|||
ToBinaryAppend(output, buffer);
|
||||
}
|
||||
|
||||
void ToUnsigned(uint32_t* a, const BigBuffer& b) {
|
||||
*a = 0;
|
||||
*a = b[0];
|
||||
}
|
||||
|
||||
void Xor(BigBuffer& a, const BigBuffer& b, const BigBuffer& c) {
|
||||
uint32_t i = 0;
|
||||
for (; b.IsUsed(i) || c.IsUsed(i); i++) {
|
||||
|
|
|
|||
|
|
@ -75,6 +75,8 @@ void ToBinary(TSGrowableArray<uint8_t>& output, const BigBuffer& buffer);
|
|||
|
||||
void ToStream(TSGrowableArray<uint8_t>& output, const BigBuffer& buffer);
|
||||
|
||||
void ToUnsigned(uint32_t* a, const BigBuffer& b);
|
||||
|
||||
void Xor(BigBuffer& a, const BigBuffer& b, const BigBuffer& c);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -167,6 +167,48 @@
|
|||
|
||||
#endif
|
||||
|
||||
#define STORM_ERROR_ASSERTION 0x85100000
|
||||
#define STORM_ERROR_BAD_ARGUMENT 0x85100065
|
||||
#define STORM_ERROR_GAME_ALREADY_STARTED 0x85100066
|
||||
#define STORM_ERROR_GAME_FULL 0x85100067
|
||||
#define STORM_ERROR_GAME_NOT_FOUND 0x85100068
|
||||
#define STORM_ERROR_GAME_TERMINATED 0x85100069
|
||||
#define STORM_ERROR_INVALID_PLAYER 0x8510006A
|
||||
#define STORM_ERROR_NO_MESSAGES_WAITING 0x8510006B
|
||||
#define STORM_ERROR_NOT_ARCHIVE 0x8510006C
|
||||
#define STORM_ERROR_NOT_ENOUGH_ARGUMENTS 0x8510006D
|
||||
#define STORM_ERROR_NOT_IMPLEMENTED 0x8510006E
|
||||
#define STORM_ERROR_NOT_IN_ARCHIVE 0x8510006F
|
||||
#define STORM_ERROR_NOT_IN_GAME 0x85100070
|
||||
#define STORM_ERROR_NOT_INITIALIZED 0x85100071
|
||||
#define STORM_ERROR_NOT_PLAYING 0x85100072
|
||||
#define STORM_ERROR_NOT_REGISTERED 0x85100073
|
||||
#define STORM_ERROR_REQUIRES_CODEC 0x85100074
|
||||
#define STORM_ERROR_REQUIRES_DDRAW 0x85100075
|
||||
#define STORM_ERROR_REQUIRES_DSOUND 0x85100076
|
||||
#define STORM_ERROR_REQUIRES_UPGRADE 0x85100077
|
||||
#define STORM_ERROR_STILL_ACTIVE 0x85100078
|
||||
#define STORM_ERROR_VERSION_MISMATCH 0x85100079
|
||||
#define STORM_ERROR_MEMORY_ALREADY_FREED 0x8510007A
|
||||
#define STORM_ERROR_MEMORY_CORRUPT 0x8510007B
|
||||
#define STORM_ERROR_MEMORY_INVALID_BLOCK 0x8510007C
|
||||
#define STORM_ERROR_MEMORY_MANAGER_INACTIVE 0x8510007D
|
||||
#define STORM_ERROR_MEMORY_NEVER_RELEASED 0x8510007E
|
||||
#define STORM_ERROR_HANDLE_NEVER_RELEASED 0x8510007F
|
||||
#define STORM_ERROR_ACCESS_OUT_OF_BOUNDS 0x85100080
|
||||
#define STORM_ERROR_MEMORY_NULL_POINTER 0x85100081
|
||||
#define STORM_ERROR_CDKEY_MISMATCH 0x85100082
|
||||
#define STORM_ERROR_DATA_FILE_CORRUPT 0x85100083
|
||||
#define STORM_ERROR_FATAL_EXCEPTION 0x85100084
|
||||
#define STORM_ERROR_GAME_TYPE_UNAVAILABLE 0x85100085
|
||||
#define STORM_ERROR_FATAL_CONDITION 0x85100086
|
||||
|
||||
#define SERR_LINECODE_FUNCTION -1
|
||||
#define SERR_LINECODE_OBJECT -2
|
||||
#define SERR_LINECODE_HANDLE -3
|
||||
#define SERR_LINECODE_FILE -4
|
||||
#define SERR_LINECODE_EXCEPTION -5 // exception handler
|
||||
|
||||
#define STORM_NO_ERROR 0x85100000
|
||||
|
||||
#define STORM_ERROR(id) (STORM_NO_ERROR | (id & 0xFFFF))
|
||||
|
|
|
|||
|
|
@ -7,20 +7,45 @@ bool HASHKEY_NONE::operator==(const HASHKEY_NONE& key) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool HASHKEY_PTR::operator==(const HASHKEY_PTR& key) {
|
||||
HASHKEY_PTR::HASHKEY_PTR() {
|
||||
this->m_key = nullptr;
|
||||
}
|
||||
|
||||
HASHKEY_PTR::HASHKEY_PTR(void* key) {
|
||||
this->m_key = key;
|
||||
}
|
||||
|
||||
HASHKEY_PTR& HASHKEY_PTR::operator=(const HASHKEY_PTR& key) {
|
||||
this->m_key = key.m_key;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HASHKEY_PTR::operator==(const HASHKEY_PTR& key) const {
|
||||
return this->m_key == key.m_key;
|
||||
}
|
||||
|
||||
void* HASHKEY_PTR::GetPtr() const {
|
||||
return this->m_key;
|
||||
}
|
||||
|
||||
HASHKEY_STR::HASHKEY_STR() {
|
||||
this->m_str = nullptr;
|
||||
}
|
||||
|
||||
HASHKEY_STR::HASHKEY_STR(const char* str) {
|
||||
this->m_str = SStrDupA(str, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
HASHKEY_STR::~HASHKEY_STR() {
|
||||
if (this->m_str) {
|
||||
SMemFree(this->m_str, __FILE__, __LINE__, 0x0);
|
||||
STORM_FREE(this->m_str);
|
||||
}
|
||||
}
|
||||
|
||||
HASHKEY_STR& HASHKEY_STR::operator=(const char* str) {
|
||||
if (this->m_str != str) {
|
||||
if (this->m_str) {
|
||||
SMemFree(this->m_str, __FILE__, __LINE__, 0x0);
|
||||
STORM_FREE(this->m_str);
|
||||
}
|
||||
|
||||
this->m_str = SStrDupA(str, __FILE__, __LINE__);
|
||||
|
|
@ -29,15 +54,91 @@ HASHKEY_STR& HASHKEY_STR::operator=(const char* str) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool HASHKEY_STR::operator==(const char* str) {
|
||||
return SStrCmp(this->m_str, str, STORM_MAX_STR) == 0;
|
||||
HASHKEY_STR& HASHKEY_STR::operator=(const HASHKEY_STR& key) {
|
||||
this->operator=(key.m_str);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HASHKEY_STR::operator==(const char* str) const {
|
||||
return SStrCmp(this->m_str, str) == 0;
|
||||
}
|
||||
|
||||
bool HASHKEY_STR::operator==(const HASHKEY_STR& key) const {
|
||||
return this->operator==(key.m_str);
|
||||
}
|
||||
|
||||
const char* HASHKEY_STR::GetString() const {
|
||||
return this->m_str;
|
||||
}
|
||||
|
||||
HASHKEY_STRI& HASHKEY_STRI::operator=(const char* str) {
|
||||
static_cast<HASHKEY_STR&>(*this) = str;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HASHKEY_STRI::operator==(const char* str) {
|
||||
return SStrCmpI(this->m_str, str, STORM_MAX_STR) == 0;
|
||||
HASHKEY_STRI& HASHKEY_STRI::operator=(const HASHKEY_STRI& key) {
|
||||
static_cast<HASHKEY_STR&>(*this) = key.m_str;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HASHKEY_STRI::operator==(const char* str) const {
|
||||
return SStrCmpI(this->m_str, str) == 0;
|
||||
}
|
||||
|
||||
bool HASHKEY_STRI::operator==(const HASHKEY_STRI& key) const {
|
||||
return this->operator==(key.m_str);
|
||||
}
|
||||
|
||||
HASHKEY_CONSTSTR::HASHKEY_CONSTSTR() {
|
||||
this->m_str = nullptr;
|
||||
}
|
||||
|
||||
HASHKEY_CONSTSTR::HASHKEY_CONSTSTR(const char* str) {
|
||||
this->m_str = str;
|
||||
}
|
||||
|
||||
HASHKEY_CONSTSTR::~HASHKEY_CONSTSTR() {
|
||||
}
|
||||
|
||||
HASHKEY_CONSTSTR& HASHKEY_CONSTSTR::operator=(const char* str) {
|
||||
this->m_str = str;
|
||||
return *this;
|
||||
}
|
||||
|
||||
HASHKEY_CONSTSTR& HASHKEY_CONSTSTR::operator=(const HASHKEY_CONSTSTR& key) {
|
||||
this->operator=(key.m_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HASHKEY_CONSTSTR::operator==(const char* str) const {
|
||||
return this->m_str == str || SStrCmp(this->m_str, str) == 0;
|
||||
}
|
||||
|
||||
bool HASHKEY_CONSTSTR::operator==(const HASHKEY_CONSTSTR& key) const {
|
||||
return this->operator==(key.m_str);
|
||||
}
|
||||
|
||||
const char* HASHKEY_CONSTSTR::GetString() const {
|
||||
return this->m_str;
|
||||
}
|
||||
|
||||
HASHKEY_CONSTSTRI& HASHKEY_CONSTSTRI::operator=(const char* str) {
|
||||
static_cast<HASHKEY_CONSTSTR&>(*this) = str;
|
||||
return *this;
|
||||
}
|
||||
|
||||
HASHKEY_CONSTSTRI& HASHKEY_CONSTSTRI::operator=(const HASHKEY_CONSTSTRI& key) {
|
||||
static_cast<HASHKEY_CONSTSTR&>(*this) = key.m_str;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HASHKEY_CONSTSTRI::operator==(const char* str) const {
|
||||
return this->m_str == str || SStrCmpI(this->m_str, str) == 0;
|
||||
}
|
||||
|
||||
bool HASHKEY_CONSTSTRI::operator==(const HASHKEY_CONSTSTRI& key) const {
|
||||
return this->operator==(key.m_str);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,37 +1,80 @@
|
|||
#ifndef STORM_HASH_HASHKEY_HPP
|
||||
#define STORM_HASH_HASHKEY_HPP
|
||||
|
||||
class HASHKEY_PTR {
|
||||
public:
|
||||
// Member variables
|
||||
void* m_key;
|
||||
|
||||
// Member functions
|
||||
bool operator==(const HASHKEY_PTR& key);
|
||||
};
|
||||
|
||||
class HASHKEY_STR {
|
||||
public:
|
||||
// Member variables
|
||||
char* m_str;
|
||||
|
||||
// Member functions
|
||||
~HASHKEY_STR();
|
||||
HASHKEY_STR& operator=(const char* str);
|
||||
bool operator==(const char* str);
|
||||
};
|
||||
|
||||
class HASHKEY_STRI : public HASHKEY_STR {
|
||||
public:
|
||||
// Member functions
|
||||
HASHKEY_STRI& operator=(const char* str);
|
||||
bool operator==(const char* str);
|
||||
};
|
||||
|
||||
class HASHKEY_NONE {
|
||||
public:
|
||||
// Member functions
|
||||
bool operator==(const HASHKEY_NONE& key);
|
||||
};
|
||||
|
||||
class HASHKEY_PTR {
|
||||
public:
|
||||
// Member functions
|
||||
HASHKEY_PTR();
|
||||
HASHKEY_PTR(void* key);
|
||||
HASHKEY_PTR& operator=(const HASHKEY_PTR& key);
|
||||
bool operator==(const HASHKEY_PTR& key) const;
|
||||
void* GetPtr() const;
|
||||
|
||||
private:
|
||||
// Member variables
|
||||
void* m_key;
|
||||
};
|
||||
|
||||
class HASHKEY_STR {
|
||||
public:
|
||||
// Member functions
|
||||
HASHKEY_STR();
|
||||
HASHKEY_STR(const char* str);
|
||||
~HASHKEY_STR();
|
||||
HASHKEY_STR& operator=(const char* str);
|
||||
HASHKEY_STR& operator=(const HASHKEY_STR& key);
|
||||
bool operator==(const char* str) const;
|
||||
bool operator==(const HASHKEY_STR& key) const;
|
||||
const char* GetString() const;
|
||||
|
||||
protected:
|
||||
// Member variables
|
||||
char* m_str;
|
||||
};
|
||||
|
||||
class HASHKEY_STRI : public HASHKEY_STR {
|
||||
public:
|
||||
// Member functions
|
||||
HASHKEY_STRI() : HASHKEY_STR() {};
|
||||
HASHKEY_STRI(const char* str) : HASHKEY_STR(str) {};
|
||||
HASHKEY_STRI& operator=(const char* str);
|
||||
HASHKEY_STRI& operator=(const HASHKEY_STRI& key);
|
||||
bool operator==(const char* str) const;
|
||||
bool operator==(const HASHKEY_STRI& key) const;
|
||||
};
|
||||
|
||||
class HASHKEY_CONSTSTR {
|
||||
public:
|
||||
// Member functions
|
||||
HASHKEY_CONSTSTR();
|
||||
HASHKEY_CONSTSTR(const char* str);
|
||||
~HASHKEY_CONSTSTR();
|
||||
HASHKEY_CONSTSTR& operator=(const char* str);
|
||||
HASHKEY_CONSTSTR& operator=(const HASHKEY_CONSTSTR& key);
|
||||
bool operator==(const char* str) const;
|
||||
bool operator==(const HASHKEY_CONSTSTR& key) const;
|
||||
const char* GetString() const;
|
||||
|
||||
protected:
|
||||
// Member variables
|
||||
const char* m_str;
|
||||
};
|
||||
|
||||
class HASHKEY_CONSTSTRI : public HASHKEY_CONSTSTR {
|
||||
public:
|
||||
// Member functions
|
||||
HASHKEY_CONSTSTRI() : HASHKEY_CONSTSTR() {};
|
||||
HASHKEY_CONSTSTRI(const char* str) : HASHKEY_CONSTSTR(str) {};
|
||||
HASHKEY_CONSTSTRI& operator=(const char* str);
|
||||
HASHKEY_CONSTSTRI& operator=(const HASHKEY_CONSTSTRI& key);
|
||||
bool operator==(const char* str) const;
|
||||
bool operator==(const HASHKEY_CONSTSTRI& key) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -43,12 +43,12 @@ THandle TSExportTableSimpleReuse<T, THandle>::GenerateUniqueHandle() {
|
|||
this->m_wrapped = 1;
|
||||
}
|
||||
|
||||
if (!this->m_wrapped || !this->Ptr(reinterpret_cast<THandle>(this->m_sequence))) {
|
||||
if (!this->m_wrapped || !this->Ptr(reinterpret_cast<THandle>(static_cast<uintptr_t>(this->m_sequence)))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return reinterpret_cast<THandle>(this->m_sequence);
|
||||
return reinterpret_cast<THandle>(static_cast<uintptr_t>(this->m_sequence));
|
||||
}
|
||||
|
||||
template <class T, class THandle>
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ T* TSExportTableSyncReuse<T, THandle, TLockedHandle, TSync>::NewLock(THandle* ha
|
|||
template <class T, class THandle, class TLockedHandle, class TSync>
|
||||
void TSExportTableSyncReuse<T, THandle, TLockedHandle, TSync>::SyncEnterLock(TLockedHandle* lockedHandlePtr, int32_t forWriting) {
|
||||
this->m_sync.Enter(forWriting);
|
||||
*lockedHandlePtr = reinterpret_cast<TLockedHandle>(forWriting ? 1 : -1);
|
||||
*lockedHandlePtr = reinterpret_cast<TLockedHandle>(static_cast<intptr_t>(forWriting ? 1 : -1));
|
||||
}
|
||||
|
||||
template <class T, class THandle, class TLockedHandle, class TSync>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ class TSHashObject {
|
|||
TSLink<T> m_linktoslot;
|
||||
TSLink<T> m_linktofull;
|
||||
TKey m_key;
|
||||
|
||||
TSHashObject & operator=(const TSHashObject &source) {
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class TSHashTable {
|
|||
|
||||
// Member functions
|
||||
uint32_t ComputeSlot(uint32_t hashval);
|
||||
void GrowListArray(uint32_t newarraysize);
|
||||
void Initialize();
|
||||
bool Initialized();
|
||||
void InternalClear(int32_t warn);
|
||||
|
|
@ -86,6 +87,31 @@ int32_t TSHashTable<T, TKey>::GetLinkOffset() {
|
|||
return offsetof(T, m_linktoslot);
|
||||
}
|
||||
|
||||
template <class T, class TKey>
|
||||
void TSHashTable<T, TKey>::GrowListArray(uint32_t newarraysize) {
|
||||
uint32_t slotmask = this->m_slotmask + 1;
|
||||
int32_t linkOffset = this->GetLinkOffset();
|
||||
|
||||
TSExplicitList<T, 0xDDDDDDDD> templist;
|
||||
templist.ChangeLinkOffset(linkOffset);
|
||||
for (uint32_t i = 0; i < slotmask; i++) {
|
||||
while (T* ptr = this->m_slotlistarray[i].Head()) {
|
||||
templist.LinkToTail(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
this->m_slotlistarray.SetCount(newarraysize);
|
||||
for (uint32_t i = 0; i < newarraysize; i++) {
|
||||
this->m_slotlistarray[i].ChangeLinkOffset(linkOffset);
|
||||
}
|
||||
|
||||
this->m_slotmask = newarraysize - 1;
|
||||
while (T* ptr = templist.Head()) {
|
||||
auto& slot = this->m_slotlistarray[this->ComputeSlot(ptr->m_hashval)];
|
||||
slot.LinkToTail(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class TKey>
|
||||
T* TSHashTable<T, TKey>::Head() {
|
||||
return this->m_fulllist.Head();
|
||||
|
|
@ -94,17 +120,13 @@ T* TSHashTable<T, TKey>::Head() {
|
|||
template <class T, class TKey>
|
||||
void TSHashTable<T, TKey>::Initialize() {
|
||||
this->m_slotmask = 3;
|
||||
this->m_slotlistarray.SetCount(4);
|
||||
this->m_slotlistarray.SetCount(this->m_slotmask + 1);
|
||||
|
||||
int32_t linkOfs = this->GetLinkOffset();
|
||||
uint32_t v3 = 0;
|
||||
STORM_EXPLICIT_LIST(T, m_linktoslot)* v4;
|
||||
auto linkOffset = this->GetLinkOffset();
|
||||
|
||||
do {
|
||||
v4 = &this->m_slotlistarray[v3];
|
||||
v4->ChangeLinkOffset(linkOfs);
|
||||
++v3;
|
||||
} while (v3 < this->m_slotmask);
|
||||
for (uint32_t slot = 0; slot <= this->m_slotmask; slot++) {
|
||||
this->m_slotlistarray[slot].ChangeLinkOffset(linkOffset);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class TKey>
|
||||
|
|
@ -141,7 +163,7 @@ void TSHashTable<T, TKey>::InternalClear(int32_t warn) {
|
|||
template <class T, class TKey>
|
||||
void TSHashTable<T, TKey>::InternalDelete(T* ptr) {
|
||||
ptr->~T();
|
||||
SMemFree(ptr, __FILE__, __LINE__, 0x0);
|
||||
STORM_FREE(ptr);
|
||||
}
|
||||
|
||||
template <class T, class TKey>
|
||||
|
|
@ -187,8 +209,26 @@ T* TSHashTable<T, TKey>::InternalNewNode(uint32_t hashval, size_t extrabytes, ui
|
|||
|
||||
template <class T, class TKey>
|
||||
int32_t TSHashTable<T, TKey>::MonitorFullness(uint32_t slot) {
|
||||
// TODO
|
||||
if (this->m_slotmask >= 0x1FFF) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this->m_fullnessIndicator > 3) {
|
||||
this->m_fullnessIndicator -= 3;
|
||||
}
|
||||
else {
|
||||
this->m_fullnessIndicator = 0;
|
||||
}
|
||||
|
||||
for (T* ptr = this->m_slotlistarray[slot].Head(); reinterpret_cast<intptr_t>(ptr) > 0; ptr = this->m_slotlistarray[slot].RawNext(ptr)) {
|
||||
this->m_fullnessIndicator++;
|
||||
if (this->m_fullnessIndicator > 13) {
|
||||
uint32_t grow_amt = 2 * this->m_slotmask + 2;
|
||||
this->m_fullnessIndicator = 0;
|
||||
this->GrowListArray(grow_amt);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -231,32 +271,12 @@ T* TSHashTable<T, TKey>::Ptr(const char* str) {
|
|||
|
||||
uint32_t hashval = SStrHashHT(str);
|
||||
|
||||
uint32_t slot = this->ComputeSlot(hashval);
|
||||
auto slotlist = &this->m_slotlistarray[slot];
|
||||
|
||||
T* v7;
|
||||
|
||||
v7 = slotlist->Head();
|
||||
|
||||
if (!v7) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
while (v7->m_hashval != hashval) {
|
||||
uint32_t v8 = this->ComputeSlot(hashval);
|
||||
auto v9 = &this->m_slotlistarray[v8];
|
||||
v7 = v9->RawNext(v7);
|
||||
|
||||
if (reinterpret_cast<intptr_t>(v7) <= 0) {
|
||||
return nullptr;
|
||||
for (T* ptr = this->m_slotlistarray[this->ComputeSlot(hashval)].Head(); reinterpret_cast<intptr_t>(ptr) > 0; ptr = this->m_slotlistarray[this->ComputeSlot(hashval)].RawNext(ptr)) {
|
||||
if (ptr->m_hashval == hashval && ptr->m_key == str) {
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(v7->m_key == str)) {
|
||||
// TODO Handle collisions
|
||||
}
|
||||
|
||||
return v7;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class T, class TKey>
|
||||
|
|
@ -265,24 +285,12 @@ T* TSHashTable<T, TKey>::Ptr(uint32_t hashval, const TKey& key) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t slot = this->ComputeSlot(hashval);
|
||||
auto slotlist = &this->m_slotlistarray[slot];
|
||||
|
||||
T* ptr = slotlist->Head();
|
||||
|
||||
if (!ptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
while (ptr->m_hashval != hashval || !(ptr->m_key == key)) {
|
||||
ptr = slotlist->RawNext(ptr);
|
||||
|
||||
if (reinterpret_cast<intptr_t>(ptr) <= 0) {
|
||||
return nullptr;
|
||||
for (T* ptr = this->m_slotlistarray[this->ComputeSlot(hashval)].Head(); reinterpret_cast<intptr_t>(ptr) > 0; ptr = this->m_slotlistarray[this->ComputeSlot(hashval)].RawNext(ptr)) {
|
||||
if (ptr->m_hashval == hashval && ptr->m_key == key) {
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class T, class TKey>
|
||||
|
|
|
|||
|
|
@ -9,23 +9,32 @@
|
|||
#include <typeinfo>
|
||||
#include <new>
|
||||
|
||||
#define STORM_LIST_LINK_AFTER 1
|
||||
#define STORM_LIST_LINK_BEFORE 2
|
||||
#define STORM_LIST_HEAD STORM_LIST_LINK_AFTER
|
||||
#define STORM_LIST_TAIL STORM_LIST_LINK_BEFORE
|
||||
|
||||
#define STORM_LIST(T) TSList<T, TSGetLink<T>>
|
||||
|
||||
template <class T, class TGetLink>
|
||||
class TSList {
|
||||
public:
|
||||
// Member variables
|
||||
ptrdiff_t m_linkoffset = 0;
|
||||
ptrdiff_t m_linkoffset;
|
||||
TSLink<T> m_terminator;
|
||||
|
||||
// Member functions
|
||||
TSList();
|
||||
TSList(const TSList& source);
|
||||
~TSList();
|
||||
void ChangeLinkOffset(ptrdiff_t linkoffset);
|
||||
void Clear();
|
||||
void Constructor();
|
||||
void CopyConstructor(const TSList& source);
|
||||
T* DeleteNode(T* ptr);
|
||||
T* Head();
|
||||
void InitializeTerminator();
|
||||
bool IsEmpty();
|
||||
bool IsLinked(T* ptr);
|
||||
TSLink<T>* Link(const T* ptr);
|
||||
void LinkNode(T* ptr, uint32_t linktype, T* existingptr);
|
||||
|
|
@ -44,7 +53,12 @@ class TSList {
|
|||
|
||||
template <class T, class TGetLink>
|
||||
TSList<T, TGetLink>::TSList() {
|
||||
this->InitializeTerminator();
|
||||
this->Constructor();
|
||||
}
|
||||
|
||||
template <class T, class TGetLink>
|
||||
TSList<T, TGetLink>::TSList(const TSList& source) {
|
||||
this->CopyConstructor(source);
|
||||
}
|
||||
|
||||
template <class T, class TGetLink>
|
||||
|
|
@ -69,12 +83,22 @@ void TSList<T, TGetLink>::Clear() {
|
|||
}
|
||||
}
|
||||
|
||||
template <class T, class TGetLink>
|
||||
void TSList<T, TGetLink>::Constructor() {
|
||||
this->SetLinkOffset(0);
|
||||
}
|
||||
|
||||
template <class T, class TGetLink>
|
||||
void TSList<T, TGetLink>::CopyConstructor(const TSList& source) {
|
||||
this->SetLinkOffset(source.m_linkoffset);
|
||||
}
|
||||
|
||||
template <class T, class TGetLink>
|
||||
T* TSList<T, TGetLink>::DeleteNode(T* ptr) {
|
||||
T* next = this->Next(ptr);
|
||||
|
||||
ptr->~T();
|
||||
SMemFree(ptr, __FILE__, __LINE__, 0);
|
||||
STORM_FREE(ptr);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
|
@ -92,6 +116,11 @@ void TSList<T, TGetLink>::InitializeTerminator() {
|
|||
this->m_terminator.m_next = reinterpret_cast<T*>(~reinterpret_cast<uintptr_t>(&this->m_terminator));
|
||||
}
|
||||
|
||||
template <class T, class TGetLink>
|
||||
bool TSList<T, TGetLink>::IsEmpty() {
|
||||
return this->Head() == nullptr;
|
||||
}
|
||||
|
||||
template <class T, class TGetLink>
|
||||
bool TSList<T, TGetLink>::IsLinked(T* ptr) {
|
||||
return TGetLink::Link(ptr, this->m_linkoffset)->IsLinked();
|
||||
|
|
@ -125,7 +154,7 @@ void TSList<T, TGetLink>::LinkNode(T* ptr, uint32_t linktype, T* existingptr) {
|
|||
TSLink<T>* v8;
|
||||
|
||||
switch (linktype) {
|
||||
case 1:
|
||||
case STORM_LIST_LINK_AFTER:
|
||||
// After existingptr
|
||||
v5->m_prevlink = v7;
|
||||
v5->m_next = v7->m_next;
|
||||
|
|
@ -134,7 +163,7 @@ void TSList<T, TGetLink>::LinkNode(T* ptr, uint32_t linktype, T* existingptr) {
|
|||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case STORM_LIST_LINK_BEFORE:
|
||||
// Before existingptr
|
||||
v8 = v7->m_prevlink;
|
||||
v5->m_prevlink = v7->m_prevlink;
|
||||
|
|
@ -152,12 +181,12 @@ void TSList<T, TGetLink>::LinkNode(T* ptr, uint32_t linktype, T* existingptr) {
|
|||
|
||||
template <class T, class TGetLink>
|
||||
void TSList<T, TGetLink>::LinkToHead(T* ptr) {
|
||||
this->LinkNode(ptr, 1, nullptr);
|
||||
this->LinkNode(ptr, STORM_LIST_HEAD, nullptr);
|
||||
}
|
||||
|
||||
template <class T, class TGetLink>
|
||||
void TSList<T, TGetLink>::LinkToTail(T* ptr) {
|
||||
this->LinkNode(ptr, 2, nullptr);
|
||||
this->LinkNode(ptr, STORM_LIST_TAIL, nullptr);
|
||||
}
|
||||
|
||||
template <class T, class TGetLink>
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ class CSBasePriorityQueue;
|
|||
class CSBasePriority {
|
||||
public:
|
||||
// Member variables
|
||||
CSBasePriorityQueue* m_queue;
|
||||
uint32_t m_index;
|
||||
CSBasePriorityQueue* m_queue = nullptr;
|
||||
uint32_t m_index = 0;
|
||||
|
||||
// Member functions
|
||||
virtual bool Compare(CSBasePriority* a) = 0;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@
|
|||
#include "storm/Hash.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
// Region flags
|
||||
#define SF_NONE 0x00000000
|
||||
#define SF_ADDING 0x00000001
|
||||
#define SF_OVERLAPS 0x00000002
|
||||
#define SF_TEMPMASK 0x00000003
|
||||
#define SF_PARAMONLY 0x00010000
|
||||
|
||||
struct SOURCE {
|
||||
RECTF rect;
|
||||
void* param;
|
||||
|
|
|
|||
|
|
@ -3,16 +3,36 @@
|
|||
|
||||
#include "storm/Handle.hpp"
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
DECLARE_HANDLE(HSRGN);
|
||||
|
||||
DECLARE_HANDLE(HLOCKEDRGN);
|
||||
DECLARE_STORM_HANDLE(HSRGN);
|
||||
DECLARE_STORM_HANDLE(HLOCKEDRGN);
|
||||
|
||||
#if defined(WHOA_RECT_USES_SCREEN_COORDINATES)
|
||||
struct RECTF {
|
||||
float left;
|
||||
float bottom;
|
||||
float right;
|
||||
float top;
|
||||
float left, top, right, bottom;
|
||||
};
|
||||
#else
|
||||
struct RECTF {
|
||||
float left, bottom, right, top;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
// NOTE: WINAPI's RECT uses `long`.
|
||||
#include <Windows.h>
|
||||
#else
|
||||
struct RECT {
|
||||
int32_t left, top, right, bottom;
|
||||
};
|
||||
#endif
|
||||
|
||||
// Combine modes
|
||||
#define SRGN_AND 1
|
||||
#define SRGN_OR 2
|
||||
#define SRGN_XOR 3
|
||||
#define SRGN_DIFF 4
|
||||
#define SRGN_COPY 5
|
||||
#define SRGN_PARAMONLY 6
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -6,8 +6,19 @@ CCritSect::CCritSect() {
|
|||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
#if defined(WHOA_STORM_C_CRIT_SECT_RECURSIVE)
|
||||
// Use of SRgnDuplicate on systems with pthreads needs recursive locking (inside s_rgntable) to prevent deadlocks.
|
||||
// This behavior doesn't appear to have carried forward to World of Warcraft, probably because SCritSect was
|
||||
// preferred.
|
||||
pthread_mutexattr_t mutex_attr;
|
||||
pthread_mutexattr_init(&mutex_attr);
|
||||
pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
|
||||
pthread_mutex_init(&this->m_critsect, &mutex_attr);
|
||||
#else
|
||||
pthread_mutex_init(&this->m_critsect, nullptr);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
CCritSect::~CCritSect() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,27 @@
|
|||
#include "storm/thread/CSRWLock.hpp"
|
||||
|
||||
CSRWLock::CSRWLock() {
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
// TODO
|
||||
SRWLock::SURWLockInitialize(&this->m_opaqueData);
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
pthread_rwlock_init(&this->m_lock, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
CSRWLock::~CSRWLock() {
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
SRWLock::SURWLockDelete(&this->m_opaqueData);
|
||||
// TODO
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
pthread_rwlock_destroy(&this->m_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSRWLock::Enter(int32_t forwriting) {
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
SRWLock::SURWLockEnter(&this->m_opaqueData, forwriting);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ class CSRWLock {
|
|||
#endif
|
||||
|
||||
// Member functions
|
||||
CSRWLock();
|
||||
~CSRWLock();
|
||||
void Enter(int32_t forwriting);
|
||||
void Leave(int32_t fromwriting);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
SSyncObject::SSyncObject() {
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
pthread_mutex_init(&this->m_mutex, 0);
|
||||
pthread_mutex_init(&this->m_mutex, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ void* S_Thread::s_SLaunchThread(void* threadParam) {
|
|||
pthread_cond_signal(¶ms->syncObject->m_cond);
|
||||
}
|
||||
|
||||
SMemFree(threadParam);
|
||||
STORM_FREE(threadParam);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@ void* SCreateThread(uint32_t (*threadProc)(void*), void* threadParam, void* a3,
|
|||
|
||||
uint32_t threadId = S_Thread::s_threadID++;
|
||||
|
||||
void* m = SMemAlloc(sizeof(SThreadParmBlock), __FILE__, __LINE__, 0x8);
|
||||
auto params = new (m) SThreadParmBlock();
|
||||
auto params = STORM_NEW_ZERO(SThreadParmBlock);
|
||||
params->threadProc = threadProc;
|
||||
params->threadParam = threadParam;
|
||||
params->threadID = threadId;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ uint32_t S_Thread::s_SLaunchThread(void* threadParam) {
|
|||
pthread_cond_signal(¶ms->syncObject->m_cond);
|
||||
}
|
||||
|
||||
SMemFree(threadParam);
|
||||
STORM_FREE(threadParam);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@ void* SCreateThread(uint32_t (*threadProc)(void*), void* threadParam, void* a3,
|
|||
|
||||
uint32_t threadId = S_Thread::s_threadID++;
|
||||
|
||||
void* m = SMemAlloc(sizeof(SThreadParmBlock), __FILE__, __LINE__, 0x8);
|
||||
auto params = new (m) SThreadParmBlock();
|
||||
auto params = STORM_NEW_ZERO(SThreadParmBlock);
|
||||
params->threadProc = threadProc;
|
||||
params->threadParam = threadParam;
|
||||
params->threadID = threadId;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,14 @@ void SRWLock::SUNNLockLeave(volatile SUNNLOCK* sunnlock) {
|
|||
// TODO
|
||||
}
|
||||
|
||||
void SRWLock::SURWLockInitialize(volatile SRWLock::SURWLOCK* surwlock) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void SRWLock::SURWLockDelete(volatile SRWLock::SURWLOCK* surwlock) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void SRWLock::SURWLockEnter(volatile SURWLOCK* surwlock, int32_t forwriting) {
|
||||
// TODO
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ class SRWLock {
|
|||
// Static functions
|
||||
static void SUNNLockEnter(volatile SUNNLOCK* sunnlock);
|
||||
static void SUNNLockLeave(volatile SUNNLOCK* sunnlock);
|
||||
static void SURWLockInitialize(volatile SURWLOCK* surwlock);
|
||||
static void SURWLockDelete(volatile SURWLOCK* surwlock);
|
||||
static void SURWLockEnter(volatile SURWLOCK* surwlock, int32_t forwriting);
|
||||
static void SURWLockLeave(volatile SURWLOCK* surwlock, int32_t fromwriting);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ DWORD WINAPI S_Thread::s_SLaunchThread(void* threadParam) {
|
|||
auto proc = params->threadProc;
|
||||
auto param = params->threadParam;
|
||||
|
||||
SMemFree(threadParam);
|
||||
STORM_FREE(threadParam);
|
||||
|
||||
auto val = proc(param);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,8 +38,7 @@ void* SCreateThread(uint32_t (*threadProc)(void*), void* threadParam, void* a3,
|
|||
*/
|
||||
}
|
||||
|
||||
void* m = SMemAlloc(sizeof(SThreadParmBlock), __FILE__, __LINE__, 0x8);
|
||||
auto params = new (m) SThreadParmBlock();
|
||||
auto params = STORM_NEW(SThreadParmBlock);
|
||||
params->threadProc = threadProc;
|
||||
params->threadParam = threadParam;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "storm/Big.hpp"
|
||||
#include "storm/big/BigData.hpp"
|
||||
#include "test/Test.hpp"
|
||||
#include "test/big/BigDataTest.hpp"
|
||||
#include <string>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "storm/Big.hpp"
|
||||
#include "storm/big/BigData.hpp"
|
||||
#include "storm/big/Ops.hpp"
|
||||
#include "test/Test.hpp"
|
||||
#include "test/big/BigDataTest.hpp"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue