parent
2e30160056
commit
d642db574b
419 changed files with 75576 additions and 0 deletions
@ -0,0 +1,9 @@ |
|||||||
|
*.db |
||||||
|
.vs/ |
||||||
|
x64/ |
||||||
|
x64_v142/ |
||||||
|
common/x64_v142/ |
||||||
|
fs/x64/ |
||||||
|
skse64/.vs/ |
||||||
|
skse64/skse64/x64/ |
||||||
|
skse64/skse64_common/x64/ |
@ -0,0 +1,102 @@ |
|||||||
|
#include "IArchive.h" |
||||||
|
#include "IErrors.h" |
||||||
|
|
||||||
|
#if ENABLE_IDYNAMICCREATE |
||||||
|
|
||||||
|
IDynamic * IArchive::iterator::Instantiate(void) |
||||||
|
{ |
||||||
|
IDataSubStream subStream(owner->theStream, GetDataOffset(), GetDataLength()); |
||||||
|
|
||||||
|
return IClassRegistry::Instantiate(GetTypeID(), &subStream); |
||||||
|
} |
||||||
|
|
||||||
|
void * IArchive::iterator::GetBuffer(UInt32 * outLength) |
||||||
|
{ |
||||||
|
HeaderEntry * entry = GetData(); |
||||||
|
UInt8 * buf = new UInt8[entry->dataLength]; |
||||||
|
|
||||||
|
owner->theStream->SetOffset(entry->dataOffset); |
||||||
|
owner->theStream->ReadBuf(buf, entry->dataLength); |
||||||
|
|
||||||
|
if(outLength) |
||||||
|
*outLength = entry->dataLength; |
||||||
|
|
||||||
|
return buf; |
||||||
|
} |
||||||
|
|
||||||
|
void IArchive::iterator::NextOfType(UInt32 typeID) |
||||||
|
{ |
||||||
|
idx++; |
||||||
|
|
||||||
|
while((GetData()->typeID != typeID) && (idx < owner->header.numEntries)) |
||||||
|
idx++; |
||||||
|
} |
||||||
|
|
||||||
|
void IArchive::iterator::PrevOfType(UInt32 typeID) |
||||||
|
{ |
||||||
|
idx--; |
||||||
|
|
||||||
|
while((GetData()->typeID != typeID) && (idx > 0)) |
||||||
|
idx--; |
||||||
|
} |
||||||
|
|
||||||
|
IArchive::IArchive() |
||||||
|
:theStream(NULL), entries(NULL), nameTable(NULL) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
IArchive::IArchive(IDataStream * stream) |
||||||
|
:theStream(NULL), entries(NULL), nameTable(NULL) |
||||||
|
{ |
||||||
|
AttachStream(stream); |
||||||
|
} |
||||||
|
|
||||||
|
IArchive::~IArchive() |
||||||
|
{ |
||||||
|
Dispose(); |
||||||
|
} |
||||||
|
|
||||||
|
void IArchive::AttachStream(IDataStream * inStream) |
||||||
|
{ |
||||||
|
Dispose(); |
||||||
|
|
||||||
|
theStream = inStream; |
||||||
|
} |
||||||
|
|
||||||
|
void IArchive::Dispose(void) |
||||||
|
{ |
||||||
|
if(entries) |
||||||
|
{ |
||||||
|
delete entries; |
||||||
|
entries = NULL; |
||||||
|
} |
||||||
|
|
||||||
|
if(nameTable) |
||||||
|
{ |
||||||
|
delete nameTable; |
||||||
|
nameTable = NULL; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void IArchive::ReadHeader(void) |
||||||
|
{ |
||||||
|
ASSERT(theStream); |
||||||
|
|
||||||
|
theStream->Rewind(); |
||||||
|
|
||||||
|
theStream->ReadBuf(&header, sizeof(FileHeader)); |
||||||
|
|
||||||
|
entries = new HeaderEntry[header.numEntries]; |
||||||
|
theStream->ReadBuf(entries, header.numEntries * sizeof(HeaderEntry)); |
||||||
|
|
||||||
|
if(header.nameTableLength) |
||||||
|
{ |
||||||
|
nameTable = new char[header.nameTableLength]; |
||||||
|
|
||||||
|
theStream->SetOffset(header.nameTableOffset); |
||||||
|
theStream->ReadBuf(nameTable, header.nameTableLength); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,95 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/IDataStream.h" |
||||||
|
#include "common/IDynamicCreate.h" |
||||||
|
|
||||||
|
#if ENABLE_IDYNAMICCREATE |
||||||
|
|
||||||
|
/**
|
||||||
|
* An object archive |
||||||
|
*
|
||||||
|
* This class implements reading and instantiating objects from an object archive. |
||||||
|
*/ |
||||||
|
class IArchive |
||||||
|
{ |
||||||
|
public: |
||||||
|
class iterator; |
||||||
|
friend iterator; |
||||||
|
|
||||||
|
IArchive(); |
||||||
|
IArchive(IDataStream * inStream); |
||||||
|
~IArchive(); |
||||||
|
|
||||||
|
void AttachStream(IDataStream * inStream); |
||||||
|
void Dispose(void); |
||||||
|
|
||||||
|
iterator begin(void) { return iterator(0, this); } |
||||||
|
iterator end(void) { return iterator(header.numEntries, this); } |
||||||
|
|
||||||
|
static const UInt32 kFileID = CHAR_CODE(0x00, 'A', 'R', 0x01); |
||||||
|
static const UInt32 kCurrentVersion = VERSION_CODE(1, 0, 0); |
||||||
|
|
||||||
|
private: |
||||||
|
struct FileHeader |
||||||
|
{ |
||||||
|
UInt32 fileID; // IArchive::kFileID
|
||||||
|
UInt32 version; // IArchive::kCurrentVersion
|
||||||
|
UInt32 numEntries; |
||||||
|
UInt32 nameTableOffset; |
||||||
|
UInt32 nameTableLength; |
||||||
|
}; |
||||||
|
|
||||||
|
struct HeaderEntry |
||||||
|
{ |
||||||
|
UInt32 typeID; |
||||||
|
UInt32 subID; |
||||||
|
UInt32 dataOffset; |
||||||
|
UInt32 dataLength; |
||||||
|
UInt32 nameOffset; |
||||||
|
}; |
||||||
|
|
||||||
|
void ReadHeader(void); |
||||||
|
|
||||||
|
IDataStream * theStream; |
||||||
|
|
||||||
|
FileHeader header; |
||||||
|
HeaderEntry * entries; |
||||||
|
|
||||||
|
char * nameTable; |
||||||
|
|
||||||
|
public: |
||||||
|
class iterator |
||||||
|
{ |
||||||
|
public: |
||||||
|
iterator() { idx = 0; owner = NULL; } |
||||||
|
iterator(UInt32 inIdx, IArchive * inArchive) { idx = inIdx; owner = inArchive; } |
||||||
|
~iterator() { } |
||||||
|
|
||||||
|
IDynamic * Instantiate(void); |
||||||
|
|
||||||
|
UInt32 GetTypeID(void) { return GetData()->typeID; } |
||||||
|
UInt32 GetSubID(void) { return GetData()->subID; } |
||||||
|
UInt32 GetDataLength(void) { return GetData()->dataLength; } |
||||||
|
char * GetName(void) { return &owner->nameTable[GetData()->nameOffset]; } |
||||||
|
void * GetBuffer(UInt32 * outLength); |
||||||
|
|
||||||
|
iterator & operator++() { Next(); return *this; } |
||||||
|
iterator & operator--() { Prev(); return *this; } |
||||||
|
|
||||||
|
void NextOfType(UInt32 typeID); |
||||||
|
void Next(void) { idx++; } |
||||||
|
|
||||||
|
void PrevOfType(UInt32 typeID); |
||||||
|
void Prev(void) { idx--; } |
||||||
|
|
||||||
|
private: |
||||||
|
HeaderEntry * GetData(void) { return &owner->entries[idx]; } |
||||||
|
|
||||||
|
UInt32 GetDataOffset(void) { return GetData()->dataOffset; } |
||||||
|
|
||||||
|
UInt32 idx; |
||||||
|
IArchive * owner; |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,58 @@ |
|||||||
|
#include "IBufferStream.h" |
||||||
|
|
||||||
|
IBufferStream::IBufferStream() |
||||||
|
:streamBuf(NULL), flags(0) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
IBufferStream::IBufferStream(const IBufferStream & rhs) |
||||||
|
{ |
||||||
|
// explicitly not supporting copy constructor for self-owned buffers
|
||||||
|
ASSERT((flags & kFlag_OwnedBuf) == 0); |
||||||
|
} |
||||||
|
|
||||||
|
IBufferStream::IBufferStream(void * buf, UInt64 inLength) |
||||||
|
:streamBuf(NULL), flags(0) |
||||||
|
{ |
||||||
|
SetBuffer(buf, inLength); |
||||||
|
} |
||||||
|
|
||||||
|
IBufferStream::~IBufferStream() |
||||||
|
{ |
||||||
|
if(flags & kFlag_OwnedBuf) |
||||||
|
{ |
||||||
|
delete [] streamBuf; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
IBufferStream & IBufferStream::operator=(IBufferStream & rhs) |
||||||
|
{ |
||||||
|
// explicitly not supporting copying for self-owned buffers
|
||||||
|
ASSERT((flags & kFlag_OwnedBuf) == 0); |
||||||
|
|
||||||
|
streamBuf = rhs.streamBuf; |
||||||
|
flags = rhs.flags; |
||||||
|
|
||||||
|
return *this; |
||||||
|
} |
||||||
|
|
||||||
|
void IBufferStream::SetBuffer(void * buf, UInt64 inLength) |
||||||
|
{ |
||||||
|
streamBuf = (UInt8 *)buf; |
||||||
|
streamLength = inLength; |
||||||
|
|
||||||
|
Rewind(); |
||||||
|
} |
||||||
|
|
||||||
|
void IBufferStream::ReadBuf(void * buf, UInt32 inLength) |
||||||
|
{ |
||||||
|
memcpy(buf, &streamBuf[streamOffset], inLength); |
||||||
|
streamOffset += inLength; |
||||||
|
} |
||||||
|
|
||||||
|
void IBufferStream::WriteBuf(const void * buf, UInt32 inLength) |
||||||
|
{ |
||||||
|
memcpy(&streamBuf[streamOffset], buf, inLength); |
||||||
|
streamOffset += inLength; |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/IDataStream.h" |
||||||
|
|
||||||
|
class IBufferStream : public IDataStream |
||||||
|
{ |
||||||
|
public: |
||||||
|
IBufferStream(); |
||||||
|
IBufferStream(const IBufferStream & rhs); |
||||||
|
IBufferStream(void * buf, UInt64 inLength); |
||||||
|
virtual ~IBufferStream(); |
||||||
|
|
||||||
|
IBufferStream & operator=(IBufferStream & rhs); |
||||||
|
|
||||||
|
void SetBuffer(void * buf, UInt64 inLength); |
||||||
|
void * GetBuffer(void) { return streamBuf; } |
||||||
|
|
||||||
|
void OwnBuffer(void) { flags |= kFlag_OwnedBuf; } |
||||||
|
void DisownBuffer(void) { flags &= ~kFlag_OwnedBuf; } |
||||||
|
|
||||||
|
// read
|
||||||
|
virtual void ReadBuf(void * buf, UInt32 inLength); |
||||||
|
|
||||||
|
// write
|
||||||
|
virtual void WriteBuf(const void * buf, UInt32 inLength); |
||||||
|
|
||||||
|
protected: |
||||||
|
UInt8 * streamBuf; |
||||||
|
UInt32 flags; |
||||||
|
|
||||||
|
enum |
||||||
|
{ |
||||||
|
kFlag_OwnedBuf = 1 << 0 |
||||||
|
}; |
||||||
|
}; |
@ -0,0 +1,116 @@ |
|||||||
|
#include "common/IConsole.h" |
||||||
|
#include <cstdarg> |
||||||
|
#include <cstring> |
||||||
|
#include <Windows.h> |
||||||
|
|
||||||
|
IConsole::IConsole() |
||||||
|
{ |
||||||
|
AllocConsole(); |
||||||
|
|
||||||
|
SetConsoleTitle("Console"); |
||||||
|
|
||||||
|
inputHandle = GetStdHandle(STD_INPUT_HANDLE); |
||||||
|
outputHandle = GetStdHandle(STD_OUTPUT_HANDLE); |
||||||
|
|
||||||
|
ASSERT_STR(inputHandle, "IConsole: couldn't get input handle"); |
||||||
|
ASSERT_STR(outputHandle, "IConsole: couldn't get output handle"); |
||||||
|
|
||||||
|
SetConsoleMode(inputHandle, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT); |
||||||
|
SetConsoleMode(outputHandle, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT); |
||||||
|
} |
||||||
|
|
||||||
|
IConsole::~IConsole() |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a string to the console |
||||||
|
*/ |
||||||
|
void IConsole::Write(char * buf) |
||||||
|
{ |
||||||
|
UInt32 charsWritten; |
||||||
|
|
||||||
|
WriteConsole(outputHandle, buf, std::strlen(buf), &charsWritten, NULL); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a formatted string to the console |
||||||
|
*
|
||||||
|
* You may specify a temp buffer to use for the formatted text, but if NULL |
||||||
|
* is used a local buffer will be provided. |
||||||
|
*
|
||||||
|
* @param buf a temporary buffer, or NULL to use the internal buffer |
||||||
|
* @param fmt the format string |
||||||
|
*/ |
||||||
|
void IConsole::Write(char * buf, UInt32 bufLen, const char * fmt, ...) |
||||||
|
{ |
||||||
|
static char tempBuf[4096]; |
||||||
|
|
||||||
|
if(!buf) |
||||||
|
{ |
||||||
|
buf = tempBuf; |
||||||
|
bufLen = sizeof(tempBuf); |
||||||
|
} |
||||||
|
|
||||||
|
va_list args; |
||||||
|
|
||||||
|
va_start(args, fmt); |
||||||
|
vsprintf_s(buf, bufLen, fmt, args); |
||||||
|
va_end(args); |
||||||
|
|
||||||
|
Write(buf); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a single character from the console |
||||||
|
*/ |
||||||
|
char IConsole::ReadChar(void) |
||||||
|
{ |
||||||
|
char data; |
||||||
|
UInt32 charsRead; |
||||||
|
|
||||||
|
ReadConsole(inputHandle, &data, 1, &charsRead, NULL); |
||||||
|
|
||||||
|
return data; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a newline-terminated string from the console |
||||||
|
*
|
||||||
|
* @param buf output buffer |
||||||
|
* @param len buffer size |
||||||
|
* @return number of characters read |
||||||
|
*/ |
||||||
|
UInt32 IConsole::ReadBuf(char * buf, UInt32 len) |
||||||
|
{ |
||||||
|
UInt32 charsRead; |
||||||
|
|
||||||
|
buf[0] = 0; |
||||||
|
|
||||||
|
do |
||||||
|
{ |
||||||
|
ReadConsole(inputHandle, buf, len, &charsRead, NULL); |
||||||
|
} |
||||||
|
while(!charsRead); |
||||||
|
|
||||||
|
int done = 0; |
||||||
|
for(UInt32 i = charsRead - 1; (i > 0) && !done; i--) |
||||||
|
{ |
||||||
|
switch(buf[i]) |
||||||
|
{ |
||||||
|
case 0x0A: |
||||||
|
case 0x0D: |
||||||
|
buf[i] = 0; |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
done = 1; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
buf[charsRead] = 0; |
||||||
|
|
||||||
|
return charsRead; |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/ITypes.h" |
||||||
|
#include "common/ISingleton.h" |
||||||
|
#include <Windows.h> |
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class for a standard Windows console |
||||||
|
*
|
||||||
|
* @todo make nonblocking |
||||||
|
*/ |
||||||
|
class IConsole : public ISingleton<IConsole> |
||||||
|
{ |
||||||
|
public: |
||||||
|
IConsole(); |
||||||
|
~IConsole(); |
||||||
|
|
||||||
|
void Write(char * buf); |
||||||
|
void Write(char * buf, UInt32 bufLen, const char * fmt, ...); |
||||||
|
|
||||||
|
char ReadChar(void); |
||||||
|
UInt32 ReadBuf(char * buf, UInt32 len); |
||||||
|
|
||||||
|
private: |
||||||
|
HANDLE inputHandle, outputHandle; |
||||||
|
}; |
@ -0,0 +1,35 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
class ICriticalSection |
||||||
|
{ |
||||||
|
public: |
||||||
|
ICriticalSection() { InitializeCriticalSection(&critSection); } |
||||||
|
~ICriticalSection() { DeleteCriticalSection(&critSection); } |
||||||
|
|
||||||
|
void Enter(void) { EnterCriticalSection(&critSection); } |
||||||
|
void Leave(void) { LeaveCriticalSection(&critSection); } |
||||||
|
bool TryEnter(void) { return TryEnterCriticalSection(&critSection) != 0; } |
||||||
|
|
||||||
|
private: |
||||||
|
CRITICAL_SECTION critSection; |
||||||
|
}; |
||||||
|
|
||||||
|
class IScopedCriticalSection |
||||||
|
{ |
||||||
|
public: |
||||||
|
IScopedCriticalSection(ICriticalSection * cs) |
||||||
|
:m_cs(cs) |
||||||
|
{ |
||||||
|
m_cs->Enter(); |
||||||
|
} |
||||||
|
|
||||||
|
~IScopedCriticalSection() |
||||||
|
{ |
||||||
|
m_cs->Leave(); |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
IScopedCriticalSection(); // undefined
|
||||||
|
|
||||||
|
ICriticalSection * m_cs; |
||||||
|
}; |
@ -0,0 +1,472 @@ |
|||||||
|
#include "IDataStream.h" |
||||||
|
|
||||||
|
/**** IDataStream *************************************************************/ |
||||||
|
|
||||||
|
IDataStream::IDataStream() |
||||||
|
:streamLength(0), streamOffset(0), swapBytes(false) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
IDataStream::~IDataStream() |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns an 8-bit value from the stream |
||||||
|
*/ |
||||||
|
UInt8 IDataStream::Read8(void) |
||||||
|
{ |
||||||
|
UInt8 out; |
||||||
|
|
||||||
|
ReadBuf(&out, sizeof(UInt8)); |
||||||
|
|
||||||
|
return out; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns a 16-bit value from the stream |
||||||
|
*/ |
||||||
|
UInt16 IDataStream::Read16(void) |
||||||
|
{ |
||||||
|
UInt16 out; |
||||||
|
|
||||||
|
ReadBuf(&out, sizeof(UInt16)); |
||||||
|
|
||||||
|
if(swapBytes) |
||||||
|
out = Swap16(out); |
||||||
|
|
||||||
|
return out; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns a 32-bit value from the stream |
||||||
|
*/ |
||||||
|
UInt32 IDataStream::Read32(void) |
||||||
|
{ |
||||||
|
UInt32 out; |
||||||
|
|
||||||
|
ReadBuf(&out, sizeof(UInt32)); |
||||||
|
|
||||||
|
if(swapBytes) |
||||||
|
out = Swap32(out); |
||||||
|
|
||||||
|
return out; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns a 64-bit value from the stream |
||||||
|
*/ |
||||||
|
UInt64 IDataStream::Read64(void) |
||||||
|
{ |
||||||
|
UInt64 out; |
||||||
|
|
||||||
|
ReadBuf(&out, sizeof(UInt64)); |
||||||
|
|
||||||
|
if(swapBytes) |
||||||
|
out = Swap64(out); |
||||||
|
|
||||||
|
return out; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns a 32-bit floating point value from the stream |
||||||
|
*/ |
||||||
|
float IDataStream::ReadFloat(void) |
||||||
|
{ |
||||||
|
UInt32 out = Read32(); |
||||||
|
|
||||||
|
return *((float *)&out); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a null-or-return-terminated string from the stream |
||||||
|
*
|
||||||
|
* If the buffer is too small to hold the entire string, it is truncated and |
||||||
|
* properly terminated. |
||||||
|
*
|
||||||
|
* @param buf the output buffer |
||||||
|
* @param bufLength the size of the output buffer |
||||||
|
* @return the number of characters written to the buffer |
||||||
|
*/ |
||||||
|
UInt32 IDataStream::ReadString(char * buf, UInt32 bufLength, char altTerminator, char altTerminator2) |
||||||
|
{ |
||||||
|
char * traverse = buf; |
||||||
|
bool breakOnReturns = false; |
||||||
|
|
||||||
|
if((altTerminator == '\n') || (altTerminator2 == '\n')) |
||||||
|
breakOnReturns = true; |
||||||
|
|
||||||
|
ASSERT_STR(bufLength > 0, "IDataStream::ReadString: zero-sized buffer"); |
||||||
|
|
||||||
|
if(bufLength == 1) |
||||||
|
{ |
||||||
|
buf[0] = 0; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
bufLength--; |
||||||
|
|
||||||
|
for(UInt32 i = 0; i < bufLength; i++) |
||||||
|
{ |
||||||
|
if(HitEOF()) break; |
||||||
|
|
||||||
|
UInt8 data = Read8(); |
||||||
|
|
||||||
|
if(breakOnReturns) |
||||||
|
{ |
||||||
|
if(data == 0x0D) |
||||||
|
{ |
||||||
|
if(Peek8() == 0x0A) |
||||||
|
Skip(1); |
||||||
|
|
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if(!data || (data == altTerminator) || (data == altTerminator2)) |
||||||
|
{ |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
*traverse++ = data; |
||||||
|
} |
||||||
|
|
||||||
|
*traverse++ = 0; |
||||||
|
|
||||||
|
return traverse - buf - 1; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns an 8-bit value from the stream without advancing the stream's position |
||||||
|
*/ |
||||||
|
UInt8 IDataStream::Peek8(void) |
||||||
|
{ |
||||||
|
IDataStream_PositionSaver saver(this); |
||||||
|
|
||||||
|
return Read8(); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns a 16-bit value from the stream without advancing the stream's position |
||||||
|
*/ |
||||||
|
UInt16 IDataStream::Peek16(void) |
||||||
|
{ |
||||||
|
IDataStream_PositionSaver saver(this); |
||||||
|
|
||||||
|
return Read16(); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns a 32-bit value from the stream without advancing the stream's position |
||||||
|
*/ |
||||||
|
UInt32 IDataStream::Peek32(void) |
||||||
|
{ |
||||||
|
IDataStream_PositionSaver saver(this); |
||||||
|
|
||||||
|
return Read32(); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns a 32-bit value from the stream without advancing the stream's position |
||||||
|
*/ |
||||||
|
UInt64 IDataStream::Peek64(void) |
||||||
|
{ |
||||||
|
IDataStream_PositionSaver saver(this); |
||||||
|
|
||||||
|
return Read64(); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns a 32-bit floating point value from the stream without advancing the stream's position |
||||||
|
*/ |
||||||
|
float IDataStream::PeekFloat(void) |
||||||
|
{ |
||||||
|
IDataStream_PositionSaver saver(this); |
||||||
|
|
||||||
|
return ReadFloat(); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads raw data into a buffer without advancing the stream's position |
||||||
|
*/ |
||||||
|
void IDataStream::PeekBuf(void * buf, UInt32 inLength) |
||||||
|
{ |
||||||
|
IDataStream_PositionSaver saver(this); |
||||||
|
|
||||||
|
ReadBuf(buf, inLength); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Skips a specified number of bytes down the stream |
||||||
|
*/ |
||||||
|
void IDataStream::Skip(SInt64 inBytes) |
||||||
|
{ |
||||||
|
SetOffset(GetOffset() + inBytes); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an 8-bit value to the stream. |
||||||
|
*/ |
||||||
|
void IDataStream::Write8(UInt8 inData) |
||||||
|
{ |
||||||
|
WriteBuf(&inData, sizeof(UInt8)); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a 16-bit value to the stream. |
||||||
|
*/ |
||||||
|
void IDataStream::Write16(UInt16 inData) |
||||||
|
{ |
||||||
|
if(swapBytes) |
||||||
|
inData = Swap16(inData); |
||||||
|
|
||||||
|
WriteBuf(&inData, sizeof(UInt16)); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a 32-bit value to the stream. |
||||||
|
*/ |
||||||
|
void IDataStream::Write32(UInt32 inData) |
||||||
|
{ |
||||||
|
if(swapBytes) |
||||||
|
inData = Swap32(inData); |
||||||
|
|
||||||
|
WriteBuf(&inData, sizeof(UInt32)); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a 64-bit value to the stream. |
||||||
|
*/ |
||||||
|
void IDataStream::Write64(UInt64 inData) |
||||||
|
{ |
||||||
|
if(swapBytes) |
||||||
|
inData = Swap64(inData); |
||||||
|
|
||||||
|
WriteBuf(&inData, sizeof(UInt64)); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a 32-bit floating point value to the stream. |
||||||
|
*/ |
||||||
|
void IDataStream::WriteFloat(float inData) |
||||||
|
{ |
||||||
|
if(swapBytes) |
||||||
|
{ |
||||||
|
UInt32 temp = *((UInt32 *)&inData); |
||||||
|
|
||||||
|
temp = Swap32(temp); |
||||||
|
|
||||||
|
WriteBuf(&temp, sizeof(UInt32)); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
WriteBuf(&inData, sizeof(float)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a null-terminated string to the stream. |
||||||
|
*/ |
||||||
|
void IDataStream::WriteString(const char * buf) |
||||||
|
{ |
||||||
|
WriteBuf(buf, std::strlen(buf) + 1); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the length of the stream |
||||||
|
*/ |
||||||
|
SInt64 IDataStream::GetLength(void) |
||||||
|
{ |
||||||
|
return streamLength; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bytes remaining in the stream |
||||||
|
*/ |
||||||
|
SInt64 IDataStream::GetRemain(void) |
||||||
|
{ |
||||||
|
return streamLength - streamOffset; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current offset into the stream |
||||||
|
*/ |
||||||
|
SInt64 IDataStream::GetOffset(void) |
||||||
|
{ |
||||||
|
return streamOffset; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether we have reached the end of the stream or not |
||||||
|
*/ |
||||||
|
bool IDataStream::HitEOF(void) |
||||||
|
{ |
||||||
|
return streamOffset >= streamLength; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the current offset into the stream |
||||||
|
*/ |
||||||
|
void IDataStream::SetOffset(SInt64 inOffset) |
||||||
|
{ |
||||||
|
streamOffset = inOffset; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables byte swapping for basic data transfers |
||||||
|
*/ |
||||||
|
void IDataStream::SwapBytes(bool inSwapBytes) |
||||||
|
{ |
||||||
|
swapBytes = inSwapBytes; |
||||||
|
} |
||||||
|
|
||||||
|
IDataStream * IDataStream::GetRootParent(void) |
||||||
|
{ |
||||||
|
IDataStream * parent = GetParent(); |
||||||
|
|
||||||
|
if(parent) |
||||||
|
return parent->GetRootParent(); |
||||||
|
else |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
void IDataStream::CopyStreams(IDataStream * out, IDataStream * in, UInt64 bufferSize, UInt8 * buf) |
||||||
|
{ |
||||||
|
in->Rewind(); |
||||||
|
|
||||||
|
bool ourBuffer = false; |
||||||
|
|
||||||
|
if(!buf) |
||||||
|
{ |
||||||
|
buf = new UInt8[bufferSize]; |
||||||
|
ourBuffer = true; |
||||||
|
} |
||||||
|
|
||||||
|
UInt64 remain = in->GetLength(); |
||||||
|
|
||||||
|
while(remain > 0) |
||||||
|
{ |
||||||
|
UInt64 transferSize = remain; |
||||||
|
|
||||||
|
if(transferSize > bufferSize) |
||||||
|
transferSize = bufferSize; |
||||||
|
|
||||||
|
in->ReadBuf(buf, transferSize); |
||||||
|
out->WriteBuf(buf, transferSize); |
||||||
|
|
||||||
|
remain -= transferSize; |
||||||
|
} |
||||||
|
|
||||||
|
if(ourBuffer) |
||||||
|
delete [] buf; |
||||||
|
} |
||||||
|
|
||||||
|
void IDataStream::CopySubStreams(IDataStream * out, IDataStream * in, UInt64 remain, UInt64 bufferSize, UInt8 * buf) |
||||||
|
{ |
||||||
|
bool ourBuffer = false; |
||||||
|
|
||||||
|
if(!buf) |
||||||
|
{ |
||||||
|
buf = new UInt8[bufferSize]; |
||||||
|
ourBuffer = true; |
||||||
|
} |
||||||
|
|
||||||
|
while(remain > 0) |
||||||
|
{ |
||||||
|
UInt64 transferSize = remain; |
||||||
|
|
||||||
|
if(transferSize > bufferSize) |
||||||
|
transferSize = bufferSize; |
||||||
|
|
||||||
|
in->ReadBuf(buf, transferSize); |
||||||
|
out->WriteBuf(buf, transferSize); |
||||||
|
|
||||||
|
remain -= transferSize; |
||||||
|
} |
||||||
|
|
||||||
|
if(ourBuffer) |
||||||
|
delete [] buf; |
||||||
|
} |
||||||
|
|
||||||
|
/**** IDataStream_PositionSaver ***********************************************/ |
||||||
|
|
||||||
|
/**
|
||||||
|
* The constructor; save the stream's position |
||||||
|
*/ |
||||||
|
IDataStream_PositionSaver::IDataStream_PositionSaver(IDataStream * tgt) |
||||||
|
{ |
||||||
|
stream = tgt; |
||||||
|
offset = tgt->GetOffset(); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* The destructor; restore the stream's saved position |
||||||
|
*/ |
||||||
|
IDataStream_PositionSaver::~IDataStream_PositionSaver() |
||||||
|
{ |
||||||
|
stream->SetOffset(offset); |
||||||
|
} |
||||||
|
|
||||||
|
/**** IDataSubStream **********************************************************/ |
||||||
|
|
||||||
|
IDataSubStream::IDataSubStream() |
||||||
|
:stream(NULL), subBase(0) |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
IDataSubStream::IDataSubStream(IDataStream * inStream, SInt64 inOffset, SInt64 inLength) |
||||||
|
{ |
||||||
|
stream = inStream; |
||||||
|
subBase = inOffset; |
||||||
|
streamLength = inLength; |
||||||
|
|
||||||
|
stream->SetOffset(inOffset); |
||||||
|
} |
||||||
|
|
||||||
|
IDataSubStream::~IDataSubStream() |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void IDataSubStream::Attach(IDataStream * inStream, SInt64 inOffset, SInt64 inLength) |
||||||
|
{ |
||||||
|
stream = inStream; |
||||||
|
subBase = inOffset; |
||||||
|
streamLength = inLength; |
||||||
|
|
||||||
|
stream->SetOffset(inOffset); |
||||||
|
} |
||||||
|
|
||||||
|
void IDataSubStream::ReadBuf(void * buf, UInt32 inLength) |
||||||
|
{ |
||||||
|
ASSERT_STR(inLength <= GetRemain(), "IDataSubStream::ReadBuf: hit eof"); |
||||||
|
|
||||||
|
if(stream->GetOffset() != subBase + streamOffset) |
||||||
|
stream->SetOffset(subBase + streamOffset); |
||||||
|
|
||||||
|
stream->ReadBuf(buf, inLength); |
||||||
|
|
||||||
|
streamOffset += inLength; |
||||||
|
} |
||||||
|
|
||||||
|
void IDataSubStream::WriteBuf(const void * buf, UInt32 inLength) |
||||||
|
{ |
||||||
|
if(stream->GetOffset() != subBase + streamOffset) |
||||||
|
stream->SetOffset(subBase + streamOffset); |
||||||
|
|
||||||
|
stream->WriteBuf(buf, inLength); |
||||||
|
|
||||||
|
streamOffset += inLength; |
||||||
|
|
||||||
|
if(streamLength < streamOffset) |
||||||
|
streamLength = streamOffset; |
||||||
|
} |
||||||
|
|
||||||
|
void IDataSubStream::SetOffset(SInt64 inOffset) |
||||||
|
{ |
||||||
|
stream->SetOffset(subBase + inOffset); |
||||||
|
streamOffset = inOffset; |
||||||
|
} |
@ -0,0 +1,102 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/IErrors.h" |
||||||
|
|
||||||
|
/**
|
||||||
|
* An arbitrary data stream |
||||||
|
*/ |
||||||
|
class IDataStream |
||||||
|
{ |
||||||
|
public: |
||||||
|
IDataStream(); |
||||||
|
virtual ~IDataStream(); |
||||||
|
|
||||||
|
// read
|
||||||
|
virtual UInt8 Read8(void); |
||||||
|
virtual UInt16 Read16(void); |
||||||
|
virtual UInt32 Read32(void); |
||||||
|
virtual UInt64 Read64(void); |
||||||
|
virtual float ReadFloat(void); |
||||||
|
virtual UInt32 ReadString(char * buf, UInt32 bufLength, char altTerminator = 0, char altTerminator2 = 0); |
||||||
|
virtual void ReadBuf(void * buf, UInt32 inLength) = 0; |
||||||
|
|
||||||
|
// peek
|
||||||
|
virtual UInt8 Peek8(void); |
||||||
|
virtual UInt16 Peek16(void); |
||||||
|
virtual UInt32 Peek32(void); |
||||||
|
virtual UInt64 Peek64(void); |
||||||
|
virtual float PeekFloat(void); |
||||||
|
virtual void PeekBuf(void * buf, UInt32 inLength); |
||||||
|
|
||||||
|
virtual void Skip(SInt64 inBytes); |
||||||
|
|
||||||
|
// write
|
||||||
|
virtual void Write8(UInt8 inData); |
||||||
|
virtual void Write16(UInt16 inData); |
||||||
|
virtual void Write32(UInt32 inData); |
||||||
|
virtual void Write64(UInt64 inData); |
||||||
|
virtual void WriteFloat(float inData); |
||||||
|
virtual void WriteString(const char * buf); |
||||||
|
virtual void WriteBuf(const void * buf, UInt32 inLength) = 0; |
||||||
|
|
||||||
|
SInt64 GetLength(void); |
||||||
|
SInt64 GetRemain(void); |
||||||
|
SInt64 GetOffset(void); |
||||||
|
bool HitEOF(void); |
||||||
|
|
||||||
|
virtual void SetOffset(SInt64 inOffset); |
||||||
|
void Rewind(void) { SetOffset(0); } |
||||||
|
|
||||||
|
void SwapBytes(bool inSwapBytes); |
||||||
|
|
||||||
|
virtual SInt64 GetParentOffset(void) { return GetOffset(); } |
||||||
|
virtual IDataStream * GetParent(void) { return NULL; } |
||||||
|
|
||||||
|
IDataStream * GetRootParent(void); |
||||||
|
|
||||||
|
static void CopyStreams(IDataStream * out, IDataStream * in, UInt64 bufferSize = 1024 * 1024, UInt8 * buf = NULL); |
||||||
|
static void CopySubStreams(IDataStream * out, IDataStream * in, UInt64 remain, UInt64 bufferSize = 1024 * 1024, UInt8 * buf = NULL); |
||||||
|
|
||||||
|
protected: |
||||||
|
SInt64 streamLength; |
||||||
|
SInt64 streamOffset; |
||||||
|
bool swapBytes; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility class to automatically save and restore the current position of an IDataStream |
||||||
|
*/ |
||||||
|
class IDataStream_PositionSaver |
||||||
|
{ |
||||||
|
public: |
||||||
|
IDataStream_PositionSaver(IDataStream * tgt); |
||||||
|
~IDataStream_PositionSaver(); |
||||||
|
|
||||||
|
private: |
||||||
|
IDataStream * stream; |
||||||
|
SInt64 offset; |
||||||
|
}; |
||||||
|
|
||||||
|
class IDataSubStream : public IDataStream |
||||||
|
{ |
||||||
|
public: |
||||||
|
IDataSubStream(); |
||||||
|
IDataSubStream(IDataStream * inStream, SInt64 inOffset, SInt64 inLength); |
||||||
|
~IDataSubStream(); |
||||||
|
|
||||||
|
void Attach(IDataStream * inStream, SInt64 inOffset, SInt64 inLength); |
||||||
|
|
||||||
|
void ReadBuf(void * buf, UInt32 inLength); |
||||||
|
void WriteBuf(const void * buf, UInt32 inLength); |
||||||
|
void SetOffset(SInt64 inOffset); |
||||||
|
|
||||||
|
virtual SInt64 GetParentOffset(void) { return stream->GetOffset(); } |
||||||
|
virtual IDataStream * GetParent(void) { return stream; } |
||||||
|
|
||||||
|
SInt64 GetSubBase(void) { return subBase; } |
||||||
|
|
||||||
|
private: |
||||||
|
IDataStream * stream; |
||||||
|
|
||||||
|
SInt64 subBase; |
||||||
|
}; |
@ -0,0 +1 @@ |
|||||||
|
#include "IDatabase.h" |
@ -0,0 +1,116 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <map> |
||||||
|
#include "common/IDataStream.h" |
||||||
|
#include "common/IFilestream.h" |
||||||
|
|
||||||
|
template <class DataType> |
||||||
|
class IDatabase |
||||||
|
{ |
||||||
|
public: |
||||||
|
typedef std::map <UInt64, DataType> DataMapType; |
||||||
|
typedef typename DataMapType::iterator DataMapIterator; |
||||||
|
|
||||||
|
static const UInt64 kGUIDMask = 0x0FFFFFFFFFFFFFFF; |
||||||
|
|
||||||
|
IDatabase() { newKeyHint = 1; } |
||||||
|
virtual ~IDatabase() { } |
||||||
|
|
||||||
|
DataType * Get(UInt64 key) |
||||||
|
{ |
||||||
|
key &= kGUIDMask; |
||||||
|
|
||||||
|
if(!key) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
DataMapType::iterator iter = theDataMap.find(key); |
||||||
|
|
||||||
|
return (iter == theDataMap.end()) ? NULL : &((*iter).second); |
||||||
|
} |
||||||
|
|
||||||
|
DataType * Alloc(UInt64 key) |
||||||
|
{ |
||||||
|
key &= kGUIDMask; |
||||||
|
|
||||||
|
if(!key) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
DataMapType::iterator iter = theDataMap.find(key); |
||||||
|
|
||||||
|
return (iter == theDataMap.end()) ? &theDataMap[key] : NULL; |
||||||
|
} |
||||||
|
|
||||||
|
DataType * Alloc(UInt64 * key) |
||||||
|
{ |
||||||
|
UInt64 newKey = newKeyHint; |
||||||
|
|
||||||
|
do |
||||||
|
{ |
||||||
|
if(!newKey) |
||||||
|
newKey++; |
||||||
|
|
||||||
|
DataMapType::iterator iter = theDataMap.find(newKey); |
||||||
|
|
||||||
|
// is 'newKey' unused?
|
||||||
|
if(iter == theDataMap.end()) |
||||||
|
{ |
||||||
|
*key = newKey; |
||||||
|
newKeyHint = (newKey + 1) & kGUIDMask; |
||||||
|
return &theDataMap[newKey]; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
++iter; |
||||||
|
if(iter == theDataMap.end()) |
||||||
|
{ |
||||||
|
newKey = 1; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
UInt64 nextKey = (newKey + 1) & kGUIDMask; |
||||||
|
if(iter->first != nextKey) |
||||||
|
{ |
||||||
|
*key = nextKey; |
||||||
|
newKeyHint = (nextKey + 1) & kGUIDMask; |
||||||
|
return &theDataMap[nextKey]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
while(1); |
||||||
|
|
||||||
|
*key = 0; |
||||||
|
|
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
void Delete(UInt64 key) |
||||||
|
{ |
||||||
|
if(key) |
||||||
|
{ |
||||||
|
key &= kGUIDMask; |
||||||
|
|
||||||
|
theDataMap.erase(key); |
||||||
|
|
||||||
|
newKeyHint = key; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void Save(IDataStream * stream); |
||||||
|
void Load(IDataStream * stream); |
||||||
|
|
||||||
|
bool SaveToFile(char * name); |
||||||
|
bool LoadFromFile(char * name); |
||||||
|
|
||||||
|
DataMapType & GetData(void) { return theDataMap; } |
||||||
|
|
||||||
|
DataMapIterator Begin(void) { return theDataMap.begin(); } |
||||||
|
DataMapIterator End(void) { return theDataMap.end(); } |
||||||
|
UInt32 Length(void) { return theDataMap.size(); } |
||||||
|
|
||||||
|
private: |
||||||
|
DataMapType theDataMap; |
||||||
|
UInt64 newKeyHint; |
||||||
|
}; |
||||||
|
|
||||||
|
#include "common/IDatabase.inc" |
Binary file not shown.
@ -0,0 +1,324 @@ |
|||||||
|
#include "common/IDebugLog.h" |
||||||
|
#include <share.h> |
||||||
|
#include "common/IFileStream.h" |
||||||
|
#include <shlobj.h> |
||||||
|
|
||||||
|
std::FILE * IDebugLog::logFile = NULL; |
||||||
|
char IDebugLog::sourceBuf[16] = { 0 }; |
||||||
|
char IDebugLog::headerText[16] = { 0 }; |
||||||
|
char IDebugLog::formatBuf[8192] = { 0 }; |
||||||
|
int IDebugLog::indentLevel = 0; |
||||||
|
int IDebugLog::rightMargin = 0; |
||||||
|
int IDebugLog::cursorPos = 0; |
||||||
|
int IDebugLog::inBlock = 0; |
||||||
|
bool IDebugLog::autoFlush = true; |
||||||
|
IDebugLog::LogLevel IDebugLog::logLevel = IDebugLog::kLevel_DebugMessage; |
||||||
|
IDebugLog::LogLevel IDebugLog::printLevel = IDebugLog::kLevel_Message; |
||||||
|
|
||||||
|
IDebugLog::IDebugLog() |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
IDebugLog::IDebugLog(const char * name) |
||||||
|
{ |
||||||
|
Open(name); |
||||||
|
} |
||||||
|
|
||||||
|
IDebugLog::~IDebugLog() |
||||||
|
{ |
||||||
|
if(logFile) |
||||||
|
fclose(logFile); |
||||||
|
} |
||||||
|
|
||||||
|
void IDebugLog::Open(const char * path) |
||||||
|
{ |
||||||
|
logFile = _fsopen(path, "w", _SH_DENYWR); |
||||||
|
|
||||||
|
if(!logFile) |
||||||
|
{ |
||||||
|
UInt32 id = 0; |
||||||
|
char name[1024]; |
||||||
|
|
||||||
|
do |
||||||
|
{ |
||||||
|
sprintf_s(name, sizeof(name), "%s%d", path, id); |
||||||
|
id++; |
||||||
|
|
||||||
|
logFile = NULL; |
||||||
|
logFile = _fsopen(name, "w", _SH_DENYWR); |
||||||
|
} |
||||||
|
while(!logFile && (id < 5)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void IDebugLog::OpenRelative(int folderID, const char * relPath) |
||||||
|
{ |
||||||
|
char path[MAX_PATH]; |
||||||
|
|
||||||
|
HRESULT err = SHGetFolderPath(NULL, folderID | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, path); |
||||||
|
if(!SUCCEEDED(err)) |
||||||
|
{ |
||||||
|
_FATALERROR("SHGetFolderPath %08X failed (result = %08X lasterr = %08X)", folderID, err, GetLastError()); |
||||||
|
} |
||||||
|
ASSERT_CODE(SUCCEEDED(err), err); |
||||||
|
|
||||||
|
strcat_s(path, sizeof(path), relPath); |
||||||
|
|
||||||
|
IFileStream::MakeAllDirs(path); |
||||||
|
|
||||||
|
Open(path); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Output a non-formatted message to the log file |
||||||
|
*
|
||||||
|
* @param message the message |
||||||
|
* @param source the source of the message, or NULL to use the previous source |
||||||
|
*/ |
||||||
|
void IDebugLog::Message(const char * message, const char * source, bool newLine) |
||||||
|
{ |
||||||
|
if(source) |
||||||
|
SetSource(source); |
||||||
|
|
||||||
|
if(inBlock) |
||||||
|
{ |
||||||
|
SeekCursor(RoundToTab((indentLevel * 4) + strlen(headerText))); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
SeekCursor(indentLevel * 4); |
||||||
|
|
||||||
|
PrintText(headerText); |
||||||
|
} |
||||||
|
|
||||||
|
PrintText(message); |
||||||
|
|
||||||
|
if(newLine) |
||||||
|
NewLine(); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Output a formatted message to the log file |
||||||
|
*
|
||||||
|
* @note It is impossible to set the source of a formatted message. |
||||||
|
* The previous source will be used. |
||||||
|
*/ |
||||||
|
void IDebugLog::FormattedMessage(const char * fmt, ...) |
||||||
|
{ |
||||||
|
va_list argList; |
||||||
|
|
||||||
|
va_start(argList, fmt); |
||||||
|
vsprintf_s(formatBuf, sizeof(formatBuf), fmt, argList); |
||||||
|
Message(formatBuf); |
||||||
|
va_end(argList); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Output a formatted message to the log file |
||||||
|
*
|
||||||
|
* @note It is impossible to set the source of a formatted message. |
||||||
|
* The previous source will be used. |
||||||
|
*/ |
||||||
|
void IDebugLog::FormattedMessage(const char * fmt, va_list args) |
||||||
|
{ |
||||||
|
vsprintf_s(formatBuf, sizeof(formatBuf), fmt, args); |
||||||
|
Message(formatBuf); |
||||||
|
} |
||||||
|
|
||||||
|
void IDebugLog::Log(LogLevel level, const char * fmt, va_list args) |
||||||
|
{ |
||||||
|
bool log = (level <= logLevel); |
||||||
|
bool print = (level <= printLevel); |
||||||
|
|
||||||
|
if(log || print) |
||||||
|
vsprintf_s(formatBuf, sizeof(formatBuf), fmt, args); |
||||||
|
|
||||||
|
if(log) |
||||||
|
Message(formatBuf); |
||||||
|
|
||||||
|
if(print) |
||||||
|
printf("%s\n", formatBuf); |
||||||
|
} |
||||||
|
|
||||||
|
void IDebugLog::LogNNL(LogLevel level, const char * fmt, va_list args) |
||||||
|
{ |
||||||
|
bool log = (level <= logLevel); |
||||||
|
bool print = (level <= printLevel); |
||||||
|
|
||||||
|
if(log || print) |
||||||
|
vsprintf_s(formatBuf, sizeof(formatBuf), fmt, args); |
||||||
|
|
||||||
|
if(log) |
||||||
|
Message(formatBuf, NULL, false); |
||||||
|
|
||||||
|
if(print) |
||||||
|
printf("%s", formatBuf); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current message source |
||||||
|
*/ |
||||||
|
void IDebugLog::SetSource(const char * source) |
||||||
|
{ |
||||||
|
strcpy_s(sourceBuf, sizeof(sourceBuf), source); |
||||||
|
strcpy_s(headerText, sizeof(headerText), "[ ]\t"); |
||||||
|
|
||||||
|
char * tgt = headerText + 1; |
||||||
|
char * src = sourceBuf; |
||||||
|
|
||||||
|
for(int i = 0; (i < 8) && *src; i++, tgt++, src++) |
||||||
|
*tgt = *src; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the current message source |
||||||
|
*/ |
||||||
|
void IDebugLog::ClearSource(void) |
||||||
|
{ |
||||||
|
sourceBuf[0] = 0; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Increase the indentation level |
||||||
|
*/ |
||||||
|
void IDebugLog::Indent(void) |
||||||
|
{ |
||||||
|
indentLevel++; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrease the indentation level |
||||||
|
*/ |
||||||
|
void IDebugLog::Outdent(void) |
||||||
|
{ |
||||||
|
if(indentLevel) |
||||||
|
indentLevel--; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Enter a logical block |
||||||
|
*/ |
||||||
|
void IDebugLog::OpenBlock(void) |
||||||
|
{ |
||||||
|
SeekCursor(indentLevel * 4); |
||||||
|
|
||||||
|
PrintText(headerText); |
||||||
|
|
||||||
|
inBlock = 1; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Close a logical block |
||||||
|
*/ |
||||||
|
void IDebugLog::CloseBlock(void) |
||||||
|
{ |
||||||
|
inBlock = 0; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable/disable autoflush |
||||||
|
*
|
||||||
|
* @param inAutoFlush autoflush state |
||||||
|
*/ |
||||||
|
void IDebugLog::SetAutoFlush(bool inAutoFlush) |
||||||
|
{ |
||||||
|
autoFlush = inAutoFlush; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Print spaces to the log |
||||||
|
*
|
||||||
|
* If possible, tabs are used instead of spaces. |
||||||
|
*/ |
||||||
|
void IDebugLog::PrintSpaces(int numSpaces) |
||||||
|
{ |
||||||
|
int originalNumSpaces = numSpaces; |
||||||
|
|
||||||
|
if(logFile) |
||||||
|
{ |
||||||
|
while(numSpaces > 0) |
||||||
|
{ |
||||||
|
if(numSpaces >= TabSize()) |
||||||
|
{ |
||||||
|
numSpaces -= TabSize(); |
||||||
|
fputc('\t', logFile); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
numSpaces--; |
||||||
|
fputc(' ', logFile); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
cursorPos += originalNumSpaces; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints raw text to the log file |
||||||
|
*/ |
||||||
|
void IDebugLog::PrintText(const char * buf) |
||||||
|
{ |
||||||
|
if(logFile) |
||||||
|
{ |
||||||
|
fputs(buf, logFile); |
||||||
|
if(autoFlush) |
||||||
|
fflush(logFile); |
||||||
|
} |
||||||
|
|
||||||
|
const char * traverse = buf; |
||||||
|
char data; |
||||||
|
|
||||||
|
while(data = *traverse++) |
||||||
|
{ |
||||||
|
if(data == '\t') |
||||||
|
cursorPos += TabSize(); |
||||||
|
else |
||||||
|
cursorPos++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves to the next line of the log file |
||||||
|
*/ |
||||||
|
void IDebugLog::NewLine(void) |
||||||
|
{ |
||||||
|
if(logFile) |
||||||
|
{ |
||||||
|
fputc('\n', logFile); |
||||||
|
|
||||||
|
if(autoFlush) |
||||||
|
fflush(logFile); |
||||||
|
} |
||||||
|
|
||||||
|
cursorPos = 0; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints spaces to align the cursor to the requested position |
||||||
|
*
|
||||||
|
* @note The cursor move will not be performed if the request would move the cursor |
||||||
|
* backwards. |
||||||
|
*/ |
||||||
|
void IDebugLog::SeekCursor(int position) |
||||||
|
{ |
||||||
|
if(position > cursorPos) |
||||||
|
PrintSpaces(position - cursorPos); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of spaces a tab would occupy at the current cursor position |
||||||
|
*/ |
||||||
|
int IDebugLog::TabSize(void) |
||||||
|
{ |
||||||
|
return ((~cursorPos) & 3) + 1; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Rounds a number of spaces to the nearest tab |
||||||
|
*/ |
||||||
|
int IDebugLog::RoundToTab(int spaces) |
||||||
|
{ |
||||||
|
return (spaces + 3) & ~3; |
||||||
|
} |
@ -0,0 +1,133 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <cstdarg> |
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple debug log file |
||||||
|
*
|
||||||
|
* This class supports prefix blocks describing the source of the log event. |
||||||
|
* It also allows logical blocks and outlining.\n |
||||||
|
*/ |
||||||
|
class IDebugLog |
||||||
|
{ |
||||||
|
public: |
||||||
|
IDebugLog(); |
||||||
|
IDebugLog(const char * name); |
||||||
|
~IDebugLog(); |
||||||
|
|
||||||
|
static void Open(const char * path); |
||||||
|
static void OpenRelative(int folderID, const char * relPath); |
||||||
|
|
||||||
|
static void Message(const char * message, const char * source = NULL, bool newLine = true); |
||||||
|
static void FormattedMessage(const char * fmt, ...); |
||||||
|
static void FormattedMessage(const char * fmt, va_list args); |
||||||
|
|
||||||
|
enum LogLevel |
||||||
|
{ |
||||||
|
kLevel_FatalError = 0, |
||||||
|
kLevel_Error, |
||||||
|
kLevel_Warning, |
||||||
|
kLevel_Message, |
||||||
|
kLevel_VerboseMessage, |
||||||
|
kLevel_DebugMessage |
||||||
|
}; |
||||||
|
|
||||||
|
static void Log(LogLevel level, const char * fmt, va_list args); |
||||||
|
static void LogNNL(LogLevel level, const char * fmt, va_list args); // No new line
|
||||||
|
|
||||||
|
static void SetSource(const char * source); |
||||||
|
static void ClearSource(void); |
||||||
|
|
||||||
|
static void Indent(void); |
||||||
|
static void Outdent(void); |
||||||
|
|
||||||
|
static void OpenBlock(void); |
||||||
|
static void CloseBlock(void); |
||||||
|
|
||||||
|
static void SetAutoFlush(bool inAutoFlush); |
||||||
|
|
||||||
|
static void SetLogLevel(LogLevel in) { logLevel = in; } |
||||||
|
static void SetPrintLevel(LogLevel in) { printLevel = in; } |
||||||
|
|
||||||
|
private: |
||||||
|
static void PrintSpaces(int numSpaces); |
||||||
|
static void PrintText(const char * buf); |
||||||
|
static void NewLine(void); |
||||||
|
|
||||||
|
static void SeekCursor(int position); |
||||||
|
|
||||||
|
static int TabSize(void); |
||||||
|
static int RoundToTab(int spaces); |
||||||
|
|
||||||
|
static FILE * logFile; //!< the output file
|
||||||
|
|
||||||
|
static char sourceBuf[16]; //!< name of current source, used in prefix
|
||||||
|
static char headerText[16]; //!< current text to use as line prefix
|
||||||
|
static char formatBuf[8192]; //!< temp buffer used for formatted messages
|
||||||
|
|
||||||
|
static int indentLevel; //!< the current indentation level (in tabs)
|
||||||
|
static int rightMargin; //!< the column at which text should be wrapped
|
||||||
|
static int cursorPos; //!< current cursor position
|
||||||
|
static int inBlock; //!< are we in a block?
|
||||||
|
|
||||||
|
static bool autoFlush; //!< automatically flush the file after writing
|
||||||
|
|
||||||
|
static LogLevel logLevel; //!< least important log level to write
|
||||||
|
static LogLevel printLevel; //!< least important log level to print
|
||||||
|
}; |
||||||
|
|
||||||
|
extern IDebugLog gLog; |
||||||
|
|
||||||
|
inline void _FATALERROR(const char * fmt, ...) |
||||||
|
{ |
||||||
|
va_list args; |
||||||
|
|
||||||
|
va_start(args, fmt); |
||||||
|
gLog.Log(IDebugLog::kLevel_FatalError, fmt, args); |
||||||
|
va_end(args); |
||||||
|
} |
||||||
|
|
||||||
|
inline void _ERROR(const char * fmt, ...) |
||||||
|
{ |
||||||
|
va_list args; |
||||||
|
|
||||||
|
va_start(args, fmt); |
||||||
|
gLog.Log(IDebugLog::kLevel_Error, fmt, args); |
||||||
|
va_end(args); |
||||||
|
} |
||||||
|
|
||||||
|
inline void _WARNING(const char * fmt, ...) |
||||||
|
{ |
||||||
|
va_list args; |
||||||
|
|
||||||
|
va_start(args, fmt); |
||||||
|
gLog.Log(IDebugLog::kLevel_Warning, fmt, args); |
||||||
|
va_end(args); |
||||||
|
} |
||||||
|
|
||||||
|
inline void _MESSAGE(const char * fmt, ...) |
||||||
|
{ |
||||||
|
va_list args; |
||||||
|
|
||||||
|
va_start(args, fmt); |
||||||
|
gLog.Log(IDebugLog::kLevel_Message, fmt, args); |
||||||
|
va_end(args); |
||||||
|
} |
||||||
|
|
||||||
|
inline void _VMESSAGE(const char * fmt, ...) |
||||||
|
{ |
||||||
|
va_list args; |
||||||
|
|
||||||
|
va_start(args, fmt); |
||||||
|
gLog.Log(IDebugLog::kLevel_VerboseMessage, fmt, args); |
||||||
|
va_end(args); |
||||||
|
} |
||||||
|
|
||||||
|
inline void _DMESSAGE(const char * fmt, ...) |
||||||
|
{ |
||||||
|
va_list args; |
||||||
|
|
||||||
|
va_start(args, fmt); |
||||||
|
gLog.Log(IDebugLog::kLevel_DebugMessage, fmt, args); |
||||||
|
va_end(args); |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
#include "IDirectoryIterator.h" |
||||||
|
#include <string> |
||||||
|
|
||||||
|
IDirectoryIterator::IDirectoryIterator(const char * path, const char * match) |
||||||
|
:m_searchHandle(INVALID_HANDLE_VALUE), m_done(false) |
||||||
|
{ |
||||||
|
if(!match) match = "*"; |
||||||
|
|
||||||
|
strcpy_s(m_path, sizeof(m_path), path); |
||||||
|
|
||||||
|
char wildcardPath[MAX_PATH]; |
||||||
|
sprintf_s(wildcardPath, sizeof(wildcardPath), "%s\\%s", path, match); |
||||||
|
|
||||||
|
m_searchHandle = FindFirstFile(wildcardPath, &m_result); |
||||||
|
if(m_searchHandle == INVALID_HANDLE_VALUE) |
||||||
|
m_done = true; |
||||||
|
} |
||||||
|
|
||||||
|
IDirectoryIterator::~IDirectoryIterator() |
||||||
|
{ |
||||||
|
if(m_searchHandle != INVALID_HANDLE_VALUE) |
||||||
|
FindClose(m_searchHandle); |
||||||
|
} |
||||||
|
|
||||||
|
void IDirectoryIterator::GetFullPath(char * out, UInt32 outLen) |
||||||
|
{ |
||||||
|
sprintf_s(out, outLen, "%s\\%s", m_path, m_result.cFileName); |
||||||
|
} |
||||||
|
|
||||||
|
std::string IDirectoryIterator::GetFullPath(void) |
||||||
|
{ |
||||||
|
return std::string(m_path) + "\\" + std::string(m_result.cFileName); |
||||||
|
} |
||||||
|
|
||||||
|
void IDirectoryIterator::Next(void) |
||||||
|
{ |
||||||
|
BOOL result = FindNextFile(m_searchHandle, &m_result); |
||||||
|
if(!result) |
||||||
|
m_done = true; |
||||||
|
} |
||||||
|
|
||||||
|
bool IDirectoryIterator::Done(void) |
||||||
|
{ |
||||||
|
return m_done; |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
class IDirectoryIterator |
||||||
|
{ |
||||||
|
public: |
||||||
|
IDirectoryIterator(const char * path, const char * match = NULL); |
||||||
|
virtual ~IDirectoryIterator(); |
||||||
|
|
||||||
|
WIN32_FIND_DATA * Get(void) { return &m_result; } |
||||||
|
void GetFullPath(char * out, UInt32 outLen); |
||||||
|
std::string GetFullPath(void); |
||||||
|
|
||||||
|
void Next(void); |
||||||
|
bool Done(void); |
||||||
|
|
||||||
|
private: |
||||||
|
IDirectoryIterator(); // undefined, disallow
|
||||||
|
|
||||||
|
HANDLE m_searchHandle; |
||||||
|
WIN32_FIND_DATA m_result; |
||||||
|
bool m_done; |
||||||
|
|
||||||
|
char m_path[MAX_PATH]; |
||||||
|
}; |
@ -0,0 +1,38 @@ |
|||||||
|
#include "IDynamicCreate.h" |
||||||
|
|
||||||
|
#if ENABLE_IDYNAMICCREATE |
||||||
|
|
||||||
|
IClassRegistry _gClassRegistry; |
||||||
|
|
||||||
|
IClassRegistry::IClassRegistry() |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
IClassRegistry::~IClassRegistry() |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
void IClassRegistry::RegisterClassInfo(UInt32 id, IDynamicType * typeInfo) |
||||||
|
{ |
||||||
|
theClassRegistry[id] = typeInfo; |
||||||
|
} |
||||||
|
|
||||||
|
IDynamicType * IClassRegistry::LookupClassInfo(UInt32 id) |
||||||
|
{ |
||||||
|
ClassRegistryType::iterator iter = theClassRegistry.find(id); |
||||||
|
|
||||||
|
return (iter == theClassRegistry.end()) ? NULL : (*iter).second; |
||||||
|
} |
||||||
|
|
||||||
|
IDynamicType * IClassRegistry::LookupClassInfo(char * name) |
||||||
|
{ |
||||||
|
for(ClassRegistryType::iterator iter = theClassRegistry.begin(); iter != theClassRegistry.end(); iter++) |
||||||
|
if(!strcmp((*iter).second->GetName(), name)) |
||||||
|
return (*iter).second; |
||||||
|
|
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,118 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <map> |
||||||
|
#include "common/IDataStream.h" |
||||||
|
#include "common/IErrors.h" |
||||||
|
|
||||||
|
// this screws with edit-and-continue and we don't use it
|
||||||
|
#define ENABLE_IDYNAMICCREATE 0 |
||||||
|
|
||||||
|
#if ENABLE_IDYNAMICCREATE |
||||||
|
|
||||||
|
//! Get a pointer to the IDynamicType for a class.
|
||||||
|
//! @note This is not a function; the parameter must be constant.
|
||||||
|
#define GetDynType(name) (&(##name##::__DYN_DynamicType)) |
||||||
|
|
||||||
|
//! Declare the members used for dynamic class creation
|
||||||
|
#define DYNAMIC_DECLARE(name) \ |
||||||
|
public: \
|
||||||
|
class __DYN_##name##_DynamicType : public IDynamicType \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
__DYN_##name##_DynamicType() { } \
|
||||||
|
~__DYN_##name##_DynamicType() { } \
|
||||||
|
\
|
||||||
|
virtual IDynamic * Create(void) { return new name; } \
|
||||||
|
virtual char * GetName(void) { return #name; } \
|
||||||
|
virtual IDynamic * Instantiate(IDataStream * stream); \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
static __DYN_##name##_DynamicType __DYN_DynamicType; \
|
||||||
|
virtual IDynamicType * __DYN_GetDynamicType(void) { return &__DYN_DynamicType; } \
|
||||||
|
\
|
||||||
|
friend __DYN_##name##_DynamicType; |
||||||
|
|
||||||
|
//! Define the members used for dynamic class creation
|
||||||
|
#define DYNAMIC_DEFINE(name) name##::__DYN_##name##_DynamicType name##::__DYN_DynamicType; |
||||||
|
|
||||||
|
//! Define a dynamic instantiation handler
|
||||||
|
#define DYNAMIC_INSTANTIATE_HANDLER(name) IDynamic * name##::__DYN_##name##_DynamicType::Instantiate(IDataStream * stream) { name * object = new name; |
||||||
|
#define END_DYNAMIC_INSTANTIATE_HANDLER return object; } |
||||||
|
|
||||||
|
//! Specifies that a dynamic class should not be instantiated automatically
|
||||||
|
#define NO_DYNAMIC_INSTANTIATE_HANDLER(name) DYNAMIC_INSTANTIATE_HANDLER(name) { HALT("attempted to instantiate " #name); } END_DYNAMIC_INSTANTIATE_HANDLER |
||||||
|
|
||||||
|
//! Casts
|
||||||
|
#define CAST(ptr, type) _DynamicCast <type>(ptr); |
||||||
|
|
||||||
|
class IDynamicType; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure virtual base class allowing dynamic creation of objects |
||||||
|
*
|
||||||
|
* To allow dynamic creation of a class, publicly inherit IDynamic, add the |
||||||
|
* macro DYNAMIC_DECLARE(classname) first in the class declaration, and add |
||||||
|
* the macro DYNAMIC_DEFINE(classname) somewhere in the class definition file. |
||||||
|
*/ |
||||||
|
class IDynamic |
||||||
|
{ |
||||||
|
public: |
||||||
|
IDynamic() { } |
||||||
|
virtual ~IDynamic() { } |
||||||
|
|
||||||
|
virtual IDynamicType * __DYN_GetDynamicType(void) = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure virtual base class allowing class instantiation and information retrieval |
||||||
|
*/ |
||||||
|
class IDynamicType |
||||||
|
{ |
||||||
|
public: |
||||||
|
IDynamicType() { } |
||||||
|
virtual ~IDynamicType() { } |
||||||
|
|
||||||
|
virtual IDynamic * Create(void) = 0; |
||||||
|
virtual char * GetName(void) = 0; |
||||||
|
|
||||||
|
virtual IDynamic * Instantiate(IDataStream * stream) = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
//!
|
||||||
|
template <typename T> |
||||||
|
T * _DynamicCast(IDynamic * ptr) |
||||||
|
{ |
||||||
|
if(ptr && (&T::__DYN_DynamicType == ptr->__DYN_GetDynamicType())) |
||||||
|
return static_cast<T *>(ptr); |
||||||
|
|
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Registry of dynamic classes |
||||||
|
*/ |
||||||
|
class IClassRegistry |
||||||
|
{ |
||||||
|
public: |
||||||
|
IClassRegistry(); |
||||||
|
~IClassRegistry(); |
||||||
|
|
||||||
|
static void RegisterClassInfo(UInt32 id, IDynamicType * typeInfo); |
||||||
|
|
||||||
|
static IDynamicType * LookupClassInfo(UInt32 id); |
||||||
|
static IDynamicType * LookupClassInfo(char * name); |
||||||
|
|
||||||
|
static IDynamic * Create(UInt32 id) { IDynamicType * info = LookupClassInfo(id); return info ? info->Create() : NULL; } |
||||||
|
static IDynamic * Create(char * name) { IDynamicType * info = LookupClassInfo(name); return info ? info->Create() : NULL; } |
||||||
|
|
||||||
|
static IDynamic * Instantiate(UInt32 id, IDataStream * stream) { IDynamicType * info = LookupClassInfo(id); return info ? info->Instantiate(stream) : NULL; } |
||||||
|
static IDynamic * Instantiate(char * name, IDataStream * stream) { IDynamicType * info = LookupClassInfo(name); return info ? info->Instantiate(stream) : NULL; } |
||||||
|
|
||||||
|
static char * GetName(UInt32 id) { IDynamicType * info = LookupClassInfo(id); return info ? info->GetName() : NULL; } |
||||||
|
|
||||||
|
private: |
||||||
|
typedef std::map <UInt32, IDynamicType *> ClassRegistryType; |
||||||
|
static ClassRegistryType theClassRegistry; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,59 @@ |
|||||||
|
#include "common/IErrors.h" |
||||||
|
#include "common/IDebugLog.h" |
||||||
|
#include <cstdlib> |
||||||
|
|
||||||
|
__declspec(noreturn) static void IErrors_Halt(void) |
||||||
|
{ |
||||||
|
// crash
|
||||||
|
*((int *)0) = 0xDEADBEEF; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Report a failed assertion and exit the program |
||||||
|
*
|
||||||
|
* @param file the file where the error occured |
||||||
|
* @param line the line number where the error occured |
||||||
|
* @param desc an error message |
||||||
|
*/ |
||||||
|
void _AssertionFailed(const char * file, unsigned long line, const char * desc) |
||||||
|
{ |
||||||
|
_FATALERROR("Assertion failed in %s (%d): %s", file, line, desc); |
||||||
|
|
||||||
|
IErrors_Halt(); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Report a failed assertion and exit the program |
||||||
|
*
|
||||||
|
* @param file the file where the error occured |
||||||
|
* @param line the line number where the error occured |
||||||
|
* @param desc an error message |
||||||
|
* @param code the error code |
||||||
|
*/ |
||||||
|
void _AssertionFailed_ErrCode(const char * file, unsigned long line, const char * desc, unsigned long long code) |
||||||
|
{ |
||||||
|
if(code & 0xFFFFFFFF00000000) |
||||||
|
_FATALERROR("Assertion failed in %s (%d): %s (code = %16I64X (%I64d))", file, line, desc, code, code); |
||||||
|
else |
||||||
|
{ |
||||||
|
UInt32 code32 = code; |
||||||
|
_FATALERROR("Assertion failed in %s (%d): %s (code = %08X (%d))", file, line, desc, code32, code32); |
||||||
|
} |
||||||
|
|
||||||
|
IErrors_Halt(); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Report a failed assertion and exit the program |
||||||
|
*
|
||||||
|
* @param file the file where the error occured |
||||||
|
* @param line the line number where the error occured |
||||||
|
* @param desc an error message |
||||||
|
* @param code the error code |
||||||
|
*/ |
||||||
|
void _AssertionFailed_ErrCode(const char * file, unsigned long line, const char * desc, const char * code) |
||||||
|
{ |
||||||
|
_FATALERROR("Assertion failed in %s (%d): %s (code = %s)", file, line, desc, code); |
||||||
|
|
||||||
|
IErrors_Halt(); |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
void _AssertionFailed(const char * file, unsigned long line, const char * desc); |
||||||
|
void _AssertionFailed_ErrCode(const char * file, unsigned long line, const char * desc, unsigned long long code); |
||||||
|
void _AssertionFailed_ErrCode(const char * file, unsigned long line, const char * desc, const char * code); |
||||||
|
|
||||||
|
//! Exit the program if the condition is not true
|
||||||
|
#define ASSERT(a) do { if(!(a)) _AssertionFailed(__FILE__, __LINE__, #a); } while(0) |
||||||
|
//! Exit the program if the condition is not true, with an error message
|
||||||
|
#define ASSERT_STR(a, b) do { if(!(a)) _AssertionFailed(__FILE__, __LINE__, b); } while(0) |
||||||
|
//! Exit the program if the condition is not true, reporting an error code
|
||||||
|
#define ASSERT_CODE(a, b) do { if(!(a)) _AssertionFailed_ErrCode(__FILE__, __LINE__, #a, b); } while(0) |
||||||
|
//! Exit the program if the condition is not true, reporting an error code and message
|
||||||
|
#define ASSERT_STR_CODE(a, b, c) do { if(!(a)) _AssertionFailed_ErrCode(__FILE__, __LINE__, b, c); } while(0) |
||||||
|
//! Exit the program with an error message
|
||||||
|
#define HALT(a) do { _AssertionFailed(__FILE__, __LINE__, a); } while(0) |
||||||
|
//! Exit the program with and error code and message
|
||||||
|
#define HALT_CODE(a, b) do { _AssertionFailed_ErrCode(__FILE__, __LINE__, a, b); } while(0) |
||||||
|
|
||||||
|
// based on the boost implementation of static asserts
|
||||||
|
template <bool x> struct StaticAssertFailure; |
||||||
|
template <> struct StaticAssertFailure <true> { enum { a = 1 }; }; |
||||||
|
template <int x> struct static_assert_test { }; |
||||||
|
|
||||||
|
#define __MACRO_JOIN__(a, b) __MACRO_JOIN_2__(a, b) |
||||||
|
#define __MACRO_JOIN_2__(a, b) __MACRO_JOIN_3__(a, b) |
||||||
|
#define __MACRO_JOIN_3__(a, b) a##b |
||||||
|
#define __PREPRO_TOKEN_STR2__(a) #a |
||||||
|
#define __PREPRO_TOKEN_STR__(a) __PREPRO_TOKEN_STR2__(a) |
||||||
|
#define __LOC__ __FILE__ "("__PREPRO_TOKEN_STR__(__LINE__)") : " |
||||||
|
|
||||||
|
#define STATIC_ASSERT(a) typedef static_assert_test <sizeof(StaticAssertFailure<(bool)(a)>)> __MACRO_JOIN__(static_assert_typedef_, __COUNTER__) |
@ -0,0 +1,48 @@ |
|||||||
|
#include "IEvent.h" |
||||||
|
|
||||||
|
IEvent::IEvent() |
||||||
|
{ |
||||||
|
theEvent = CreateEvent(NULL, true, true, NULL); |
||||||
|
ASSERT(theEvent); |
||||||
|
|
||||||
|
blockCount.Set(0); |
||||||
|
} |
||||||
|
|
||||||
|
IEvent::~IEvent() |
||||||
|
{ |
||||||
|
CloseHandle(theEvent); |
||||||
|
} |
||||||
|
|
||||||
|
bool IEvent::Block(void) |
||||||
|
{ |
||||||
|
if(blockCount.Increment() == 1) |
||||||
|
return (ResetEvent(theEvent) != 0); |
||||||
|
else |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool IEvent::UnBlock(void) |
||||||
|
{ |
||||||
|
if(blockCount.Decrement() == 0) |
||||||
|
return (SetEvent(theEvent) != 0); |
||||||
|
else |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool IEvent::Wait(UInt32 timeout) |
||||||
|
{ |
||||||
|
switch(WaitForSingleObject(theEvent, timeout)) |
||||||
|
{ |
||||||
|
case WAIT_ABANDONED: |
||||||
|
HALT("IEvent::Wait: got abandoned event"); |
||||||
|
return false; |
||||||
|
|
||||||
|
case WAIT_OBJECT_0: |
||||||
|
return true; |
||||||
|
|
||||||
|
default: |
||||||
|
case WAIT_TIMEOUT: |
||||||
|
gLog.FormattedMessage("IEvent::Wait: timeout"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/IInterlockedLong.h" |
||||||
|
|
||||||
|
class IEvent |
||||||
|
{ |
||||||
|
public: |
||||||
|
static const UInt32 kDefaultTimeout = 1000 * 10; |
||||||
|
|
||||||
|
IEvent(); |
||||||
|
~IEvent(); |
||||||
|
|
||||||
|
bool Block(void); |
||||||
|
bool UnBlock(void); |
||||||
|
bool Wait(UInt32 timeout = kDefaultTimeout); |
||||||
|
|
||||||
|
bool IsBlocked(void) { return blockCount.Get() > 0; } |
||||||
|
|
||||||
|
private: |
||||||
|
HANDLE theEvent; |
||||||
|
IInterlockedLong blockCount; |
||||||
|
}; |
@ -0,0 +1,85 @@ |
|||||||
|
#include "IFIFO.h" |
||||||
|
|
||||||
|
IFIFO::IFIFO(UInt32 length) |
||||||
|
{ |
||||||
|
fifoBuf = new UInt8[length]; |
||||||
|
fifoBufSize = length; |
||||||
|
fifoBase = 0; |
||||||
|
fifoDataLength = 0; |
||||||
|
} |
||||||
|
|
||||||
|
IFIFO::~IFIFO() |
||||||
|
{ |
||||||
|
delete fifoBuf; |
||||||
|
} |
||||||
|
|
||||||
|
bool IFIFO::Push(UInt8 * buf, UInt32 length) |
||||||
|
{ |
||||||
|
// would that overflow the buffer?
|
||||||
|
if(length > GetBufferRemain()) |
||||||
|
return false; |
||||||
|
|
||||||
|
UInt32 writeOffset = GetWriteOffset(); |
||||||
|
|
||||||
|
// will this cross the end of the buffer?
|
||||||
|
if(writeOffset + length > fifoBufSize) |
||||||
|
{ |
||||||
|
UInt32 segmentLength = fifoBufSize - writeOffset; |
||||||
|
|
||||||
|
std::memcpy(&fifoBuf[writeOffset], buf, segmentLength); |
||||||
|
std::memcpy(fifoBuf, &buf[segmentLength], length - segmentLength); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
std::memcpy(&fifoBuf[writeOffset], buf, length); |
||||||
|
} |
||||||
|
|
||||||
|
// update pointers
|
||||||
|
fifoDataLength += length; |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool IFIFO::Pop(UInt8 * buf, UInt32 length) |
||||||
|
{ |
||||||
|
bool result = Peek(buf, length); |
||||||
|
|
||||||
|
// update pointers if we were successful
|
||||||
|
if(result) |
||||||
|
{ |
||||||
|
fifoDataLength -= length; |
||||||
|
fifoBase = ToRawOffset(fifoBase + length); |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
bool IFIFO::Peek(UInt8 * buf, UInt32 length) |
||||||
|
{ |
||||||
|
// would that underflow the buffer?
|
||||||
|
if(length > fifoDataLength) |
||||||
|
return false; |
||||||
|
|
||||||
|
// will this cross the end of the buffer?
|
||||||
|
if(fifoBase + length > fifoBufSize) |
||||||
|
{ |
||||||
|
UInt32 segmentLength = fifoBufSize - fifoBase; |
||||||
|
|
||||||
|
std::memcpy(buf, &fifoBuf[fifoBase], segmentLength); |
||||||
|
std::memcpy(&buf[segmentLength], fifoBuf, length - segmentLength); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
std::memcpy(buf, &fifoBuf[fifoBase], length); |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
void IFIFO::Clear(void) |
||||||
|
{ |
||||||
|
fifoDataLength = 0; |
||||||
|
|
||||||
|
// this isn't needed, but staying away from the buffer end is always good
|
||||||
|
fifoBase = 0; |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
class IFIFO |
||||||
|
{ |
||||||
|
public: |
||||||
|
IFIFO(UInt32 length = 0); |
||||||
|
virtual ~IFIFO(); |
||||||
|
|
||||||
|
virtual bool Push(UInt8 * buf, UInt32 length); |
||||||
|
virtual bool Pop(UInt8 * buf, UInt32 length); |
||||||
|
virtual bool Peek(UInt8 * buf, UInt32 length); |
||||||
|
virtual void Clear(void); |
||||||
|
|
||||||
|
UInt32 GetBufferSize(void) { return fifoBufSize; } |
||||||
|
UInt32 GetBufferRemain(void) { return fifoBufSize - fifoDataLength; } |
||||||
|
UInt32 GetDataLength(void) { return fifoDataLength; } |
||||||
|
|
||||||
|
private: |
||||||
|
UInt32 ToRawOffset(UInt32 in) { return in % fifoBufSize; } |
||||||
|
UInt32 ToDataOffset(UInt32 in) { return ToRawOffset(fifoBase + in); } |
||||||
|
UInt32 GetWriteOffset(void) { return ToDataOffset(fifoDataLength); } |
||||||
|
|
||||||
|
UInt8 * fifoBuf; |
||||||
|
UInt32 fifoBufSize; // size of the buffer (in bytes)
|
||||||
|
UInt32 fifoBase; // pointer to the beginning of the data block
|
||||||
|
UInt32 fifoDataLength; // size of the data block
|
||||||
|
}; |
@ -0,0 +1,240 @@ |
|||||||
|
#include "IFileStream.h" |
||||||
|
#include "IDebugLog.h" |
||||||
|
#include "IErrors.h" |
||||||
|
#include <direct.h> |
||||||
|
|
||||||
|
IFileStream::IFileStream() |
||||||
|
:theFile(INVALID_HANDLE_VALUE) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
IFileStream::IFileStream(const char * name) |
||||||
|
:theFile(INVALID_HANDLE_VALUE) |
||||||
|
{ |
||||||
|
Open(name); |
||||||
|
} |
||||||
|
|
||||||
|
IFileStream::~IFileStream() |
||||||
|
{ |
||||||
|
Close(); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a file for reading and attaches it to the stream |
||||||
|
*/ |
||||||
|
bool IFileStream::Open(const char * name) |
||||||
|
{ |
||||||
|
Close(); |
||||||
|
|
||||||
|
theFile = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |
||||||
|
if(theFile != INVALID_HANDLE_VALUE) |
||||||
|
{ |
||||||
|
LARGE_INTEGER temp; |
||||||
|
|
||||||
|
GetFileSizeEx(theFile, &temp); |
||||||
|
|
||||||
|
streamLength = temp.QuadPart; |
||||||
|
streamOffset = 0; |
||||||
|
} |
||||||
|
|
||||||
|
return theFile != INVALID_HANDLE_VALUE; |
||||||
|
} |
||||||
|
|
||||||
|
static UINT_PTR CALLBACK BrowseEventProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
bool IFileStream::BrowseOpen(void) |
||||||
|
{ |
||||||
|
bool result = false; |
||||||
|
OPENFILENAME info; |
||||||
|
char path[4096]; |
||||||
|
|
||||||
|
path[0] = 0; |
||||||
|
|
||||||
|
info.lStructSize = sizeof(info); |
||||||
|
info.hwndOwner = NULL; |
||||||
|
info.hInstance = NULL; |
||||||
|
info.lpstrFilter = NULL; |
||||||
|
info.lpstrCustomFilter = NULL; |
||||||
|
info.nMaxCustFilter = 0; |
||||||
|
info.nFilterIndex = 0; |
||||||
|
info.lpstrFile = path; |
||||||
|
info.nMaxFile = sizeof(path); |
||||||
|
info.lpstrFileTitle = NULL; |
||||||
|
info.nMaxFileTitle = 0; |
||||||
|
info.lpstrInitialDir = NULL; |
||||||
|
info.lpstrTitle = NULL; |
||||||
|
info.Flags = OFN_EXPLORER | OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_ENABLEHOOK | OFN_NOCHANGEDIR; |
||||||
|
info.lpstrDefExt = NULL; |
||||||
|
info.lCustData = NULL; |
||||||
|
info.lpfnHook = BrowseEventProc; |
||||||
|
info.lpTemplateName = NULL; |
||||||
|
// info.pvReserved = NULL;
|
||||||
|
// info.dwReserved = NULL;
|
||||||
|
// info.FlagsEx = 0;
|
||||||
|
|
||||||
|
if(GetOpenFileName(&info)) |
||||||
|
{ |
||||||
|
result = Open(path); |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new file for writing, overwriting any previously-existing files, |
||||||
|
* and attaches it to the stream |
||||||
|
*/ |
||||||
|
bool IFileStream::Create(const char * name) |
||||||
|
{ |
||||||
|
Close(); |
||||||
|
|
||||||
|
theFile = CreateFile(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
||||||
|
if(theFile != INVALID_HANDLE_VALUE) |
||||||
|
{ |
||||||
|
streamLength = 0; |
||||||
|
streamOffset = 0; |
||||||
|
} |
||||||
|
|
||||||
|
return theFile != INVALID_HANDLE_VALUE; |
||||||
|
} |
||||||
|
|
||||||
|
bool IFileStream::BrowseCreate(const char * defaultName, const char * defaultPath, const char * title) |
||||||
|
{ |
||||||
|
bool result = false; |
||||||
|
OPENFILENAME info; |
||||||
|
char path[4096]; |
||||||
|
|
||||||
|
if(defaultName) |
||||||
|
strcpy_s(path, sizeof(path), defaultName); |
||||||
|
|
||||||
|
info.lStructSize = sizeof(info); |
||||||
|
info.hwndOwner = NULL; |
||||||
|
info.hInstance = NULL; |
||||||
|
info.lpstrFilter = NULL; |
||||||
|
info.lpstrCustomFilter = NULL; |
||||||
|
info.nMaxCustFilter = 0; |
||||||
|
info.nFilterIndex = 0; |
||||||
|
info.lpstrFile = path; |
||||||
|
info.nMaxFile = sizeof(path); |
||||||
|
info.lpstrFileTitle = NULL; |
||||||
|
info.nMaxFileTitle = 0; |
||||||
|
info.lpstrInitialDir = defaultPath; |
||||||
|
info.lpstrTitle = title; |
||||||
|
info.Flags = OFN_EXPLORER | OFN_ENABLESIZING | OFN_ENABLEHOOK | |
||||||
|
OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; |
||||||
|
info.lpstrDefExt = NULL; |
||||||
|
info.lCustData = NULL; |
||||||
|
info.lpfnHook = BrowseEventProc; |
||||||
|
info.lpTemplateName = NULL; |
||||||
|
// info.pvReserved = NULL;
|
||||||
|
// info.dwReserved = NULL;
|
||||||
|
// info.FlagsEx = 0;
|
||||||
|
|
||||||
|
if(GetSaveFileName(&info)) |
||||||
|
{ |
||||||
|
result = Create(path); |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the current file |
||||||
|
*/ |
||||||
|
void IFileStream::Close(void) |
||||||
|
{ |
||||||
|
if(theFile) |
||||||
|
{ |
||||||
|
CloseHandle(theFile); |
||||||
|
theFile = INVALID_HANDLE_VALUE; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void IFileStream::ReadBuf(void * buf, UInt32 inLength) |
||||||
|
{ |
||||||
|
UInt32 bytesRead; |
||||||
|
|
||||||
|
ReadFile(theFile, buf, inLength, &bytesRead, NULL); |
||||||
|
|
||||||
|
streamOffset += bytesRead; |
||||||
|
} |
||||||
|
|
||||||
|
void IFileStream::WriteBuf(const void * buf, UInt32 inLength) |
||||||
|
{ |
||||||
|
UInt32 bytesWritten; |
||||||
|
|
||||||
|
// check for file expansion
|
||||||
|
if(streamOffset > streamLength) |
||||||
|
SetEndOfFile(theFile); |
||||||
|
|
||||||
|
WriteFile(theFile, buf, inLength, &bytesWritten, NULL); |
||||||
|
|
||||||
|
streamOffset += bytesWritten; |
||||||
|
|
||||||
|
if(streamLength < streamOffset) |
||||||
|
streamLength = streamOffset; |
||||||
|
} |
||||||
|
|
||||||
|
void IFileStream::SetOffset(SInt64 inOffset) |
||||||
|
{ |
||||||
|
LARGE_INTEGER temp; |
||||||
|
|
||||||
|
temp.QuadPart = inOffset; |
||||||
|
|
||||||
|
SetFilePointerEx(theFile, temp, NULL, FILE_BEGIN); |
||||||
|
streamOffset = inOffset; |
||||||
|
} |
||||||
|
|
||||||
|
void IFileStream::SetLength(UInt64 length) |
||||||
|
{ |
||||||
|
SetOffset(length); |
||||||
|
SetEndOfFile(theFile); |
||||||
|
|
||||||
|
streamLength = length; |
||||||
|
} |
||||||
|
|
||||||
|
// ### TODO: get rid of buf
|
||||||
|
void IFileStream::MakeAllDirs(const char * path) |
||||||
|
{ |
||||||
|
char buf[1024]; |
||||||
|
char * traverse = buf; |
||||||
|
|
||||||
|
while(1) |
||||||
|
{ |
||||||
|
char data = *path++; |
||||||
|
|
||||||
|
if(!data) |
||||||
|
break; |
||||||
|
|
||||||
|
if((data == '\\') || (data == '/')) |
||||||
|
{ |
||||||
|
*traverse = 0; |
||||||
|
_mkdir(buf); |
||||||
|
} |
||||||
|
|
||||||
|
*traverse++ = data; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
char * IFileStream::ExtractFileName(char * path) |
||||||
|
{ |
||||||
|
char * traverse = path; |
||||||
|
char * lastSlash = NULL; |
||||||
|
|
||||||
|
while(1) |
||||||
|
{ |
||||||
|
char data = *traverse++; |
||||||
|
|
||||||
|
if((data == '\\') || (data == '/')) |
||||||
|
lastSlash = traverse; |
||||||
|
|
||||||
|
if(!data) |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
return lastSlash; |
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/IDataStream.h" |
||||||
|
|
||||||
|
/**
|
||||||
|
* An input file stream |
||||||
|
*/ |
||||||
|
class IFileStream : public IDataStream |
||||||
|
{ |
||||||
|
public: |
||||||
|
IFileStream(); |
||||||
|
IFileStream(const char * name); |
||||||
|
~IFileStream(); |
||||||
|
|
||||||
|
bool Open(const char * name); |
||||||
|
bool BrowseOpen(void); |
||||||
|
|
||||||
|
bool Create(const char * name); |
||||||
|
bool BrowseCreate(const char * defaultName = NULL, const char * defaultPath = NULL, const char * title = NULL); |
||||||
|
|
||||||
|
void Close(void); |
||||||
|
|
||||||
|
HANDLE GetHandle(void) { return theFile; } |
||||||
|
|
||||||
|
virtual void ReadBuf(void * buf, UInt32 inLength); |
||||||
|
virtual void WriteBuf(const void * buf, UInt32 inLength); |
||||||
|
virtual void SetOffset(SInt64 inOffset); |
||||||
|
|
||||||
|
// can truncate. implicitly seeks to the end of the file
|
||||||
|
void SetLength(UInt64 length); |
||||||
|
|
||||||
|
static void MakeAllDirs(const char * path); |
||||||
|
static char * ExtractFileName(char * path); |
||||||
|
|
||||||
|
protected: |
||||||
|
HANDLE theFile; |
||||||
|
}; |
@ -0,0 +1,3 @@ |
|||||||
|
#include "IInterlockedLong.h" |
||||||
|
|
||||||
|
// all functions are inlined
|
@ -0,0 +1,19 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
struct IInterlockedLong |
||||||
|
{ |
||||||
|
public: |
||||||
|
long Increment(void) { return InterlockedIncrement(&value); } |
||||||
|
long Decrement(void) { return InterlockedDecrement(&value); } |
||||||
|
long Get(void) { return value; } |
||||||
|
long Set(long in) { return InterlockedExchange(&value, in); } |
||||||
|
long TrySetIf(long newValue, long expectedOldValue) |
||||||
|
{ return InterlockedCompareExchange(&value, newValue, expectedOldValue); } |
||||||
|
|
||||||
|
// interlock variable semantics
|
||||||
|
bool Claim(void) { return TrySetIf(1, 0) == 0; } |
||||||
|
bool Release(void) { return TrySetIf(0, 1) == 1; } |
||||||
|
|
||||||
|
private: |
||||||
|
volatile long value; |
||||||
|
}; |
@ -0,0 +1,91 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
// ILink members must be public
|
||||||
|
template <typename T> |
||||||
|
struct ILink |
||||||
|
{ |
||||||
|
static const UInt32 s_offset; |
||||||
|
|
||||||
|
ILink <T> * next; |
||||||
|
ILink <T> * prev; |
||||||
|
|
||||||
|
T * GetObj(void) { return (T *)(((uintptr_t)this) - s_offset); } |
||||||
|
|
||||||
|
static ILink <T> * GetLink(T * obj) { return (ILink <T> *)(((uintptr_t)obj) + s_offset); } |
||||||
|
|
||||||
|
void Unlink(void) |
||||||
|
{ |
||||||
|
if(next) next->prev = prev; |
||||||
|
if(prev) prev->next = next; |
||||||
|
|
||||||
|
next = prev = NULL; |
||||||
|
} |
||||||
|
|
||||||
|
void LinkBefore(T * obj) |
||||||
|
{ |
||||||
|
LinkBefore(GetLink(obj)); |
||||||
|
} |
||||||
|
|
||||||
|
void LinkAfter(T * obj) |
||||||
|
{ |
||||||
|
LinkAfter(GetLink(obj)); |
||||||
|
} |
||||||
|
|
||||||
|
void LinkBefore(ILink <T> * link) |
||||||
|
{ |
||||||
|
link->next = this; |
||||||
|
link->prev = prev; |
||||||
|
|
||||||
|
if(prev) |
||||||
|
{ |
||||||
|
prev->next = link; |
||||||
|
} |
||||||
|
|
||||||
|
prev = link; |
||||||
|
} |
||||||
|
|
||||||
|
void LinkAfter(ILink <T> * link) |
||||||
|
{ |
||||||
|
link->next = next; |
||||||
|
link->prev = this; |
||||||
|
|
||||||
|
if(next) |
||||||
|
{ |
||||||
|
next->prev = link; |
||||||
|
} |
||||||
|
|
||||||
|
next = link; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
template <typename T> |
||||||
|
struct ILinkedList |
||||||
|
{ |
||||||
|
ILink <T> begin; |
||||||
|
ILink <T> end; |
||||||
|
|
||||||
|
void Reset(void) |
||||||
|
{ |
||||||
|
begin.next = &end; |
||||||
|
begin.prev = NULL; |
||||||
|
end.next = NULL; |
||||||
|
end.prev = &begin; |
||||||
|
} |
||||||
|
|
||||||
|
void PushFront(T * obj) |
||||||
|
{ |
||||||
|
ILink <T> * objLink = ILink <T>::GetLink(obj); |
||||||
|
|
||||||
|
objLink->next = begin.next; |
||||||
|
objLink->prev = &begin; |
||||||
|
|
||||||
|
if(objLink->next) |
||||||
|
{ |
||||||
|
objLink->next->prev = objLink; |
||||||
|
} |
||||||
|
|
||||||
|
begin.next = objLink; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
#define ILINK_INIT(baseType, memberName) template <typename T> const UInt32 ILink <T>::s_offset = offsetof(baseType, memberName) |
@ -0,0 +1,43 @@ |
|||||||
|
#include "IMemPool.h" |
||||||
|
|
||||||
|
void Test_IMemPool(void) |
||||||
|
{ |
||||||
|
IMemPool <UInt32, 3> pool; |
||||||
|
|
||||||
|
_DMESSAGE("main: pool test"); |
||||||
|
gLog.Indent(); |
||||||
|
|
||||||
|
_DMESSAGE("start"); |
||||||
|
pool.Dump(); |
||||||
|
|
||||||
|
UInt32 * data0, * data1, * data2; |
||||||
|
|
||||||
|
data0 = pool.Allocate(); |
||||||
|
_DMESSAGE("alloc0 = %08X", data0); |
||||||
|
pool.Dump(); |
||||||
|
|
||||||
|
data1 = pool.Allocate(); |
||||||
|
_DMESSAGE("alloc1 = %08X", data1); |
||||||
|
pool.Dump(); |
||||||
|
|
||||||
|
data2 = pool.Allocate(); |
||||||
|
_DMESSAGE("alloc2 = %08X", data2); |
||||||
|
pool.Dump(); |
||||||
|
|
||||||
|
_DMESSAGE("free0 %08X", data0); |
||||||
|
pool.Free(data0); |
||||||
|
pool.Dump(); |
||||||
|
|
||||||
|
data0 = pool.Allocate(); |
||||||
|
_DMESSAGE("alloc0 = %08X", data0); |
||||||
|
pool.Dump(); |
||||||
|
|
||||||
|
_DMESSAGE("free2 %08X", data2); |
||||||
|
pool.Free(data2); |
||||||
|
pool.Dump(); |
||||||
|
|
||||||
|
_DMESSAGE("done"); |
||||||
|
pool.Dump(); |
||||||
|
|
||||||
|
gLog.Outdent(); |
||||||
|
} |
@ -0,0 +1,312 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/ICriticalSection.h" |
||||||
|
|
||||||
|
template <typename T, UInt32 size> |
||||||
|
class IMemPool |
||||||
|
{ |
||||||
|
public: |
||||||
|
IMemPool() |
||||||
|
:m_free(NULL), m_alloc(NULL) |
||||||
|
{ |
||||||
|
Reset(); |
||||||
|
} |
||||||
|
|
||||||
|
~IMemPool() { Clear(); } |
||||||
|
|
||||||
|
void Reset(void) |
||||||
|
{ |
||||||
|
for(UInt32 i = 0; i < size - 1; i++) |
||||||
|
{ |
||||||
|
m_items[i].next = &m_items[i + 1]; |
||||||
|
} |
||||||
|
|
||||||
|
m_items[size - 1].next = NULL; |
||||||
|
m_free = m_items; |
||||||
|
m_alloc = NULL; |
||||||
|
} |
||||||
|
|
||||||
|
T * Allocate(void) |
||||||
|
{ |
||||||
|
if(m_free) |
||||||
|
{ |
||||||
|
PoolItem * item = m_free; |
||||||
|
m_free = m_free->next; |
||||||
|
|
||||||
|
item->next = m_alloc; |
||||||
|
m_alloc = item; |
||||||
|
|
||||||
|
T * obj = item->GetObj(); |
||||||
|
|
||||||
|
new (obj) T; |
||||||
|
return obj; |
||||||
|
} |
||||||
|
|
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
void Free(T * obj) |
||||||
|
{ |
||||||
|
PoolItem * item = reinterpret_cast <PoolItem *>(obj); |
||||||
|
|
||||||
|
if(item == m_alloc) |
||||||
|
{ |
||||||
|
m_alloc = item->next; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
PoolItem * traverse = m_alloc; |
||||||
|
while(traverse->next != item) |
||||||
|
traverse = traverse->next; |
||||||
|
traverse->next = traverse->next->next; |
||||||
|
} |
||||||
|
|
||||||
|
item->next = m_free; |
||||||
|
m_free = item; |
||||||
|
|
||||||
|
obj->~T(); |
||||||
|
} |
||||||
|
|
||||||
|
UInt32 GetSize(void) { return size; } |
||||||
|
|
||||||
|
T * Begin(void) |
||||||
|
{ |
||||||
|
T * result = NULL; |
||||||
|
|
||||||
|
if(m_alloc) |
||||||
|
result = m_alloc->GetObj(); |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
T * Next(T * obj) |
||||||
|
{ |
||||||
|
PoolItem * item = reinterpret_cast <PoolItem *>(obj); |
||||||
|
PoolItem * next = item->next; |
||||||
|
T * result = NULL; |
||||||
|
|
||||||
|
if(next) |
||||||
|
result = next->GetObj(); |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
void Dump(void) |
||||||
|
{ |
||||||
|
gLog.Indent(); |
||||||
|
|
||||||
|
_DMESSAGE("free:"); |
||||||
|
gLog.Indent(); |
||||||
|
for(PoolItem * traverse = m_free; traverse; traverse = traverse->next) |
||||||
|
_DMESSAGE("%08X", traverse); |
||||||
|
gLog.Outdent(); |
||||||
|
|
||||||
|
_DMESSAGE("alloc:"); |
||||||
|
gLog.Indent(); |
||||||
|
for(PoolItem * traverse = m_alloc; traverse; traverse = traverse->next) |
||||||
|
_DMESSAGE("%08X", traverse); |
||||||
|
gLog.Outdent(); |
||||||
|
|
||||||
|
gLog.Outdent(); |
||||||
|
} |
||||||
|
|
||||||
|
bool Full(void) |
||||||
|
{ |
||||||
|
return m_free == NULL; |
||||||
|
} |
||||||
|
|
||||||
|
bool Empty(void) |
||||||
|
{ |
||||||
|
return m_alloc == NULL; |
||||||
|
} |
||||||
|
|
||||||
|
void Clear(void) |
||||||
|
{ |
||||||
|
while(m_alloc) |
||||||
|
Free(m_alloc->GetObj()); |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
struct PoolItem |
||||||
|
{ |
||||||
|
UInt8 obj[sizeof(T)]; |
||||||
|
PoolItem * next; |
||||||
|
|
||||||
|
T * GetObj(void) { return reinterpret_cast <T *>(obj); } |
||||||
|
}; |
||||||
|
|
||||||
|
PoolItem m_items[size]; |
||||||
|
PoolItem * m_free; |
||||||
|
PoolItem * m_alloc; |
||||||
|
}; |
||||||
|
|
||||||
|
template <typename T, UInt32 size> |
||||||
|
class IBasicMemPool |
||||||
|
{ |
||||||
|
public: |
||||||
|
IBasicMemPool() |
||||||
|
:m_free(NULL) |
||||||
|
{ |
||||||
|
Reset(); |
||||||
|
} |
||||||
|
|
||||||
|
~IBasicMemPool() { } |
||||||
|
|
||||||
|
void Reset(void) |
||||||
|
{ |
||||||
|
for(UInt32 i = 0; i < size - 1; i++) |
||||||
|
{ |
||||||
|
m_items[i].next = &m_items[i + 1]; |
||||||
|
} |
||||||
|
|
||||||
|
m_items[size - 1].next = NULL; |
||||||
|
m_free = m_items; |
||||||
|
} |
||||||
|
|
||||||
|
T * Allocate(void) |
||||||
|
{ |
||||||
|
if(m_free) |
||||||
|
{ |
||||||
|
PoolItem * item = m_free; |
||||||
|
m_free = m_free->next; |
||||||
|
|
||||||
|
T * obj = item->GetObj(); |
||||||
|
|
||||||
|
new (obj) T; |
||||||
|
return obj; |
||||||
|
} |
||||||
|
|
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
void Free(T * obj) |
||||||
|
{ |
||||||
|
obj->~T(); |
||||||
|
|
||||||
|
PoolItem * item = reinterpret_cast <PoolItem *>(obj); |
||||||
|
|
||||||
|
item->next = m_free; |
||||||
|
m_free = item; |
||||||
|
} |
||||||
|
|
||||||
|
UInt32 GetSize(void) { return size; } |
||||||
|
|
||||||
|
bool Full(void) |
||||||
|
{ |
||||||
|
return m_free == NULL; |
||||||
|
} |
||||||
|
|
||||||
|
UInt32 GetIdx(T * obj) |
||||||
|
{ |
||||||
|
PoolItem * item = reinterpret_cast <PoolItem *>(obj); |
||||||
|
|
||||||
|
return item - m_items; |
||||||
|
} |
||||||
|
|
||||||
|
T * GetByID(UInt32 id) |
||||||
|
{ |
||||||
|
return m_items[id].GetObj(); |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
union PoolItem |
||||||
|
{ |
||||||
|
UInt8 obj[sizeof(T)]; |
||||||
|
PoolItem * next; |
||||||
|
|
||||||
|
T * GetObj(void) { return reinterpret_cast <T *>(obj); } |
||||||
|
}; |
||||||
|
|
||||||
|
PoolItem m_items[size]; |
||||||
|
PoolItem * m_free; |
||||||
|
}; |
||||||
|
|
||||||
|
template <typename T, UInt32 size> |
||||||
|
class IThreadSafeBasicMemPool |
||||||
|
{ |
||||||
|
public: |
||||||
|
IThreadSafeBasicMemPool() |
||||||
|
:m_free(NULL) |
||||||
|
{ |
||||||
|
Reset(); |
||||||
|
} |
||||||
|
|
||||||
|
~IThreadSafeBasicMemPool() { } |
||||||
|
|
||||||
|
void Reset(void) |
||||||
|
{ |
||||||
|
m_mutex.Enter(); |
||||||
|
|
||||||
|
for(UInt32 i = 0; i < size - 1; i++) |
||||||
|
{ |
||||||
|
m_items[i].next = &m_items[i + 1]; |
||||||
|
} |
||||||
|
|
||||||
|
m_items[size - 1].next = NULL; |
||||||
|
m_free = m_items; |
||||||
|
|
||||||
|
m_mutex.Leave(); |
||||||
|
} |
||||||
|
|
||||||
|
T * Allocate(void) |
||||||
|
{ |
||||||
|
T * result = NULL; |
||||||
|
|
||||||
|
m_mutex.Enter(); |
||||||
|
|
||||||
|
if(m_free) |
||||||
|
{ |
||||||
|
PoolItem * item = m_free; |
||||||
|
m_free = m_free->next; |
||||||
|
|
||||||
|
m_mutex.Leave(); |
||||||
|
|
||||||
|
result = item->GetObj(); |
||||||
|
|
||||||
|
new (result) T; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
m_mutex.Leave(); |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
void Free(T * obj) |
||||||
|
{ |
||||||
|
obj->~T(); |
||||||
|
|
||||||
|
PoolItem * item = reinterpret_cast <PoolItem *>(obj); |
||||||
|
|
||||||
|
m_mutex.Enter(); |
||||||
|
|
||||||
|
item->next = m_free; |
||||||
|
m_free = item; |
||||||
|
|
||||||
|
m_mutex.Leave(); |
||||||
|
} |
||||||
|
|
||||||
|
UInt32 GetSize(void) { return size; } |
||||||
|
|
||||||
|
bool Full(void) |
||||||
|
{ |
||||||
|
return m_free == NULL; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
union PoolItem |
||||||
|
{ |
||||||
|
UInt8 obj[sizeof(T)]; |
||||||
|
PoolItem * next; |
||||||
|
|
||||||
|
T * GetObj(void) { return reinterpret_cast <T *>(obj); } |
||||||
|
}; |
||||||
|
|
||||||
|
PoolItem m_items[size]; |
||||||
|
PoolItem * m_free; |
||||||
|
|
||||||
|
ICriticalSection m_mutex; |
||||||
|
}; |
||||||
|
|
||||||
|
void Test_IMemPool(void); |
@ -0,0 +1,34 @@ |
|||||||
|
#include "IMutex.h" |
||||||
|
|
||||||
|
IMutex::IMutex() |
||||||
|
{ |
||||||
|
theMutex = CreateMutex(NULL, true, NULL); |
||||||
|
} |
||||||
|
|
||||||
|
IMutex::~IMutex() |
||||||
|
{ |
||||||
|
CloseHandle(theMutex); |
||||||
|
} |
||||||
|
|
||||||
|
bool IMutex::Wait(UInt32 timeout) |
||||||
|
{ |
||||||
|
switch(WaitForSingleObject(theMutex, timeout)) |
||||||
|
{ |
||||||
|
case WAIT_ABANDONED: |
||||||
|
HALT("IMutex::Wait: got abandoned mutex"); |
||||||
|
return false; |
||||||
|
|
||||||
|
case WAIT_OBJECT_0: |
||||||
|
return true; |
||||||
|
|
||||||
|
default: |
||||||
|
case WAIT_TIMEOUT: |
||||||
|
gLog.FormattedMessage("IMutex::Wait: timeout"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void IMutex::Release(void) |
||||||
|
{ |
||||||
|
ASSERT_STR(ReleaseMutex(theMutex), "IMutex::Release: failed to release mutex"); |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
class IMutex |
||||||
|
{ |
||||||
|
public: |
||||||
|
static const UInt32 kDefaultTimeout = 1000 * 10; |
||||||
|
|
||||||
|
IMutex(); |
||||||
|
~IMutex(); |
||||||
|
|
||||||
|
bool Wait(UInt32 timeout = kDefaultTimeout); |
||||||
|
void Release(void); |
||||||
|
|
||||||
|
private: |
||||||
|
HANDLE theMutex; |
||||||
|
}; |
@ -0,0 +1,60 @@ |
|||||||
|
#include "IPipeClient.h" |
||||||
|
|
||||||
|
IPipeClient::IPipeClient() |
||||||
|
:m_pipe(INVALID_HANDLE_VALUE) |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
IPipeClient::~IPipeClient() |
||||||
|
{ |
||||||
|
Close(); |
||||||
|
} |
||||||
|
|
||||||
|
bool IPipeClient::Open(const char * name) |
||||||
|
{ |
||||||
|
Close(); |
||||||
|
|
||||||
|
m_pipe = CreateFile( |
||||||
|
name, |
||||||
|
GENERIC_READ | GENERIC_WRITE, |
||||||
|
0, |
||||||
|
NULL, |
||||||
|
OPEN_EXISTING, |
||||||
|
0, |
||||||
|
NULL); |
||||||
|
|
||||||
|
return m_pipe != INVALID_HANDLE_VALUE; |
||||||
|
} |
||||||
|
|
||||||
|
void IPipeClient::Close(void) |
||||||
|
{ |
||||||
|
if(m_pipe != INVALID_HANDLE_VALUE) |
||||||
|
{ |
||||||
|
CloseHandle(m_pipe); |
||||||
|
m_pipe = INVALID_HANDLE_VALUE; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool IPipeClient::ReadMessage(UInt8 * buf, UInt32 length) |
||||||
|
{ |
||||||
|
UInt32 bytesRead; |
||||||
|
|
||||||
|
ReadFile(m_pipe, buf, length, &bytesRead, NULL); |
||||||
|
|
||||||
|
IPipeServer::MessageHeader * header = (IPipeServer::MessageHeader *)buf; |
||||||
|
|
||||||
|
return |
||||||
|
(bytesRead >= sizeof(IPipeServer::MessageHeader)) && // has a valid header
|
||||||
|
(bytesRead >= (sizeof(IPipeServer::MessageHeader) + header->length)); |
||||||
|
} |
||||||
|
|
||||||
|
bool IPipeClient::WriteMessage(IPipeServer::MessageHeader * msg) |
||||||
|
{ |
||||||
|
UInt32 bytesWritten; |
||||||
|
UInt32 length = sizeof(IPipeServer::MessageHeader) + msg->length; |
||||||
|
|
||||||
|
WriteFile(m_pipe, msg, length, &bytesWritten, NULL); |
||||||
|
|
||||||
|
return bytesWritten >= length; |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/IPipeServer.h" |
||||||
|
|
||||||
|
class IPipeClient |
||||||
|
{ |
||||||
|
public: |
||||||
|
IPipeClient(); |
||||||
|
virtual ~IPipeClient(); |
||||||
|
|
||||||
|
bool Open(const char * name); |
||||||
|
void Close(void); |
||||||
|
|
||||||
|
bool ReadMessage(UInt8 * buf, UInt32 length); |
||||||
|
bool WriteMessage(IPipeServer::MessageHeader * msg); |
||||||
|
|
||||||
|
private: |
||||||
|
HANDLE m_pipe; |
||||||
|
std::string m_name; |
||||||
|
}; |
@ -0,0 +1,74 @@ |
|||||||
|
#include "IPipeServer.h" |
||||||
|
|
||||||
|
IPipeServer::IPipeServer() |
||||||
|
:m_pipe(INVALID_HANDLE_VALUE) |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
IPipeServer::~IPipeServer() |
||||||
|
{ |
||||||
|
Close(); |
||||||
|
} |
||||||
|
|
||||||
|
bool IPipeServer::Open(const char * name) |
||||||
|
{ |
||||||
|
Close(); |
||||||
|
|
||||||
|
m_pipe = CreateNamedPipe( |
||||||
|
name, |
||||||
|
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, |
||||||
|
PIPE_TYPE_MESSAGE | PIPE_TYPE_MESSAGE | PIPE_WAIT, |
||||||
|
PIPE_UNLIMITED_INSTANCES, |
||||||
|
8192, 8192, |
||||||
|
10 * 1000, // 10 seconds
|
||||||
|
NULL); |
||||||
|
|
||||||
|
return m_pipe != INVALID_HANDLE_VALUE; |
||||||
|
} |
||||||
|
|
||||||
|
void IPipeServer::Close(void) |
||||||
|
{ |
||||||
|
if(m_pipe != INVALID_HANDLE_VALUE) |
||||||
|
{ |
||||||
|
CloseHandle(m_pipe); |
||||||
|
m_pipe = INVALID_HANDLE_VALUE; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool IPipeServer::WaitForClient(void) |
||||||
|
{ |
||||||
|
bool result = ConnectNamedPipe(m_pipe, NULL) != 0; |
||||||
|
|
||||||
|
// already connected?
|
||||||
|
if(!result) |
||||||
|
{ |
||||||
|
if(GetLastError() == ERROR_PIPE_CONNECTED) |
||||||
|
result = true; |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
bool IPipeServer::ReadMessage(UInt8 * buf, UInt32 length) |
||||||
|
{ |
||||||
|
UInt32 bytesRead; |
||||||
|
|
||||||
|
ReadFile(m_pipe, buf, length, &bytesRead, NULL); |
||||||
|
|
||||||
|
MessageHeader * header = (MessageHeader *)buf; |
||||||
|
|
||||||
|
return |
||||||
|
(bytesRead >= sizeof(MessageHeader)) && // has a valid header
|
||||||
|
(bytesRead >= (sizeof(MessageHeader) + header->length)); |
||||||
|
} |
||||||
|
|
||||||
|
bool IPipeServer::WriteMessage(MessageHeader * msg) |
||||||
|
{ |
||||||
|
UInt32 bytesWritten; |
||||||
|
UInt32 length = sizeof(MessageHeader) + msg->length; |
||||||
|
|
||||||
|
WriteFile(m_pipe, msg, length, &bytesWritten, NULL); |
||||||
|
|
||||||
|
return bytesWritten >= length; |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
class IPipeServer |
||||||
|
{ |
||||||
|
public: |
||||||
|
struct MessageHeader |
||||||
|
{ |
||||||
|
UInt32 type; |
||||||
|
UInt32 length; |
||||||
|
}; |
||||||
|
|
||||||
|
IPipeServer(); |
||||||
|
virtual ~IPipeServer(); |
||||||
|
|
||||||
|
bool Open(const char * name); |
||||||
|
void Close(void); |
||||||
|
|
||||||
|
bool WaitForClient(void); |
||||||
|
|
||||||
|
bool ReadMessage(UInt8 * buf, UInt32 length); |
||||||
|
bool WriteMessage(MessageHeader * msg); |
||||||
|
|
||||||
|
private: |
||||||
|
HANDLE m_pipe; |
||||||
|
}; |
@ -0,0 +1 @@ |
|||||||
|
#include "IPrefix.h" |
@ -0,0 +1,23 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
// 4018 - signed/unsigned mismatch
|
||||||
|
// 4200 - zero-sized array
|
||||||
|
// 4244 - loss of data by assignment
|
||||||
|
// 4267 - possible loss of data (truncation)
|
||||||
|
// 4305 - truncation by assignment
|
||||||
|
// 4288 - disable warning for crap microsoft extension screwing up the scope of variables defined in for loops
|
||||||
|
// 4311 - pointer truncation
|
||||||
|
// 4312 - pointer extension
|
||||||
|
#pragma warning(disable: 4018 4200 4244 4267 4305 4288 4312 4311) |
||||||
|
|
||||||
|
#include <cstdlib> |
||||||
|
#include <cstdio> |
||||||
|
#include <cstring> |
||||||
|
#include <string> |
||||||
|
#include "common/ITypes.h" |
||||||
|
#include "common/IErrors.h" |
||||||
|
#include "common/IDynamicCreate.h" |
||||||
|
#include "common/IDebugLog.h" |
||||||
|
#include "common/ISingleton.h" |
||||||
|
#include <winsock2.h> |
||||||
|
#include <Windows.h> |
@ -0,0 +1 @@ |
|||||||
|
#include "IRangeMap.h" |
@ -0,0 +1,215 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <map> |
||||||
|
|
||||||
|
// t_key must be a numeric type
|
||||||
|
// ### you can't create a range taking up the entire range of t_key
|
||||||
|
// ### (could be done by switching from start/length -> start/end)
|
||||||
|
template <typename t_key, typename t_data> |
||||||
|
class IRangeMap |
||||||
|
{ |
||||||
|
public: |
||||||
|
struct Entry |
||||||
|
{ |
||||||
|
bool Contains(t_key addr, t_key base) |
||||||
|
{ |
||||||
|
return (addr >= base) && (addr <= (base + length - 1)); |
||||||
|
} |
||||||
|
|
||||||
|
t_key length; |
||||||
|
t_data data; |
||||||
|
}; |
||||||
|
|
||||||
|
typedef std::map <t_key, Entry> EntryMapType; |
||||||
|
typedef typename EntryMapType::iterator Iterator; |
||||||
|
|
||||||
|
IRangeMap() |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
virtual ~IRangeMap() |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
void Clear(void) |
||||||
|
{ |
||||||
|
m_entries.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
t_data * Add(t_key start, t_key length) |
||||||
|
{ |
||||||
|
t_data * result = NULL; |
||||||
|
Entry * entry = NULL; |
||||||
|
|
||||||
|
t_key end = start + length - 1; |
||||||
|
|
||||||
|
if(end >= start) // check for overflow ### should also check for overflow on length - 1, but that's pedantic
|
||||||
|
{ |
||||||
|
// special-case empty lists
|
||||||
|
if(m_entries.empty()) |
||||||
|
{ |
||||||
|
entry = &m_entries[start]; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
// collision check
|
||||||
|
|
||||||
|
EntryMapType::iterator iter = m_entries.lower_bound(start); |
||||||
|
// iter contains the first entry at or after start (or null)
|
||||||
|
|
||||||
|
if(iter == m_entries.begin()) |
||||||
|
{ |
||||||
|
// there can't be anything before this entry
|
||||||
|
// so we only need to check if it's colliding with us
|
||||||
|
|
||||||
|
if(iter->first > end) |
||||||
|
{ |
||||||
|
// can't provide a hint because we're inserting at the top
|
||||||
|
entry = &m_entries[start]; |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
// see if this entry doesn't collide
|
||||||
|
// can be null (null entries don't collide)
|
||||||
|
if((iter == m_entries.end()) || (iter->first > end)) |
||||||
|
{ |
||||||
|
// we didn't get the first entry in the map
|
||||||
|
// and there is at least one entry in the map
|
||||||
|
// therefore there's an entry before iter
|
||||||
|
EntryMapType::iterator preIter = iter; |
||||||
|
preIter--; |
||||||
|
|
||||||
|
// check if this collides
|
||||||
|
// guaranteed to be the first entry before start
|
||||||
|
t_key preEnd = preIter->first + preIter->second.length - 1; |
||||||
|
|
||||||
|
if(preEnd < start) |
||||||
|
{ |
||||||
|
// cool, everything's fine, allocate it
|
||||||
|
EntryMapType::iterator newEntry = m_entries.insert(preIter, EntryMapType::value_type(start, Entry())); |
||||||
|
entry = &newEntry->second; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// set up the entry
|
||||||
|
if(entry) |
||||||
|
{ |
||||||
|
entry->length = length; |
||||||
|
|
||||||
|
result = &entry->data; |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
t_data * Lookup(t_key addr, t_key * base = NULL, t_key * length = NULL) |
||||||
|
{ |
||||||
|
t_data * result = NULL; |
||||||
|
|
||||||
|
EntryMapType::iterator iter = LookupIter(addr); |
||||||
|
if(iter != m_entries.end()) |
||||||
|
{ |
||||||
|
if(base) *base = iter->first; |
||||||
|
if(length) *length = iter->second.length; |
||||||
|
|
||||||
|
result = &iter->second.data; |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
bool Erase(t_key addr, t_key * base = NULL, t_key * length = NULL) |
||||||
|
{ |
||||||
|
bool result = false; |
||||||
|
|
||||||
|
EntryMapType::iterator iter = LookupIter(addr); |
||||||
|
if(iter != m_entries.end()) |
||||||
|
{ |
||||||
|
if(base) *base = iter->first; |
||||||
|
if(length) *length = iter->second.length; |
||||||
|
|
||||||
|
m_entries.erase(iter); |
||||||
|
|
||||||
|
result = true; |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
t_key GetDataRangeLength(t_data * data) |
||||||
|
{ |
||||||
|
Entry * entry = reinterpret_cast <Entry *>(reinterpret_cast <UInt8 *>(data) - offsetof(Entry, data)); |
||||||
|
|
||||||
|
return entry->length; |
||||||
|
} |
||||||
|
|
||||||
|
typename EntryMapType::iterator LookupIter(t_key addr) |
||||||
|
{ |
||||||
|
EntryMapType::iterator result = m_entries.end(); |
||||||
|
|
||||||
|
if(!m_entries.empty()) |
||||||
|
{ |
||||||
|
// we need to find the last entry less than or equal to addr
|
||||||
|
|
||||||
|
// find the first entry not less than addr
|
||||||
|
EntryMapType::iterator iter = m_entries.lower_bound(addr); |
||||||
|
|
||||||
|
// iter is either equal to addr, greater than addr, or the end
|
||||||
|
if(iter == m_entries.end()) |
||||||
|
{ |
||||||
|
// iter is the end
|
||||||
|
// can only be in the entry before this
|
||||||
|
// which does exist because map isn't empty
|
||||||
|
--iter; |
||||||
|
|
||||||
|
if(iter->second.Contains(addr, iter->first)) |
||||||
|
{ |
||||||
|
result = iter; |
||||||
|
} |
||||||
|
} |
||||||
|
// at this point iter must be valid
|
||||||
|
else if(iter->first > addr) |
||||||
|
{ |
||||||
|
// iter is greater than addr
|
||||||
|
// can only be in the entry before this
|
||||||
|
// but there may not be an entry before this
|
||||||
|
|
||||||
|
if(iter != m_entries.begin()) |
||||||
|
{ |
||||||
|
--iter; |
||||||
|
|
||||||
|
if(iter->second.Contains(addr, iter->first)) |
||||||
|
{ |
||||||
|
result = iter; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
// iter is equal to addr and matches
|
||||||
|
result = iter; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
typename EntryMapType::iterator Begin(void) |
||||||
|
{ |
||||||
|
return m_entries.begin(); |
||||||
|
} |
||||||
|
|
||||||
|
typename EntryMapType::iterator End(void) |
||||||
|
{ |
||||||
|
return m_entries.end(); |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
EntryMapType m_entries; |
||||||
|
}; |
@ -0,0 +1,43 @@ |
|||||||
|
#include "IReadWriteLock.h" |
||||||
|
|
||||||
|
IReadWriteLock::IReadWriteLock() |
||||||
|
{ |
||||||
|
readCount.Set(0); |
||||||
|
readBlocker.UnBlock(); |
||||||
|
writeBlocker.UnBlock(); |
||||||
|
} |
||||||
|
|
||||||
|
IReadWriteLock::~IReadWriteLock() |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
void IReadWriteLock::StartRead(void) |
||||||
|
{ |
||||||
|
enterBlocker.Enter(); |
||||||
|
readBlocker.Wait(); |
||||||
|
if(readCount.Increment() == 1) |
||||||
|
writeBlocker.Block(); |
||||||
|
enterBlocker.Leave(); |
||||||
|
} |
||||||
|
|
||||||
|
void IReadWriteLock::EndRead(void) |
||||||
|
{ |
||||||
|
if(!readCount.Decrement()) |
||||||
|
writeBlocker.UnBlock(); |
||||||
|
} |
||||||
|
|
||||||
|
void IReadWriteLock::StartWrite(void) |
||||||
|
{ |
||||||
|
writeMutex.Enter(); |
||||||
|
enterBlocker.Enter(); |
||||||
|
readBlocker.Block(); |
||||||
|
writeBlocker.Wait(); |
||||||
|
enterBlocker.Leave(); |
||||||
|
} |
||||||
|
|
||||||
|
void IReadWriteLock::EndWrite(void) |
||||||
|
{ |
||||||
|
readBlocker.UnBlock(); |
||||||
|
writeMutex.Leave(); |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/ICriticalSection.h" |
||||||
|
#include "common/IEvent.h" |
||||||
|
#include "common/IInterlockedLong.h" |
||||||
|
|
||||||
|
class IReadWriteLock |
||||||
|
{ |
||||||
|
public: |
||||||
|
IReadWriteLock(); |
||||||
|
~IReadWriteLock(); |
||||||
|
|
||||||
|
void StartRead(void); |
||||||
|
void EndRead(void); |
||||||
|
void StartWrite(void); |
||||||
|
void EndWrite(void); |
||||||
|
|
||||||
|
private: |
||||||
|
IEvent readBlocker; |
||||||
|
IEvent writeBlocker; |
||||||
|
ICriticalSection enterBlocker; |
||||||
|
ICriticalSection writeMutex; |
||||||
|
IInterlockedLong readCount; |
||||||
|
}; |
@ -0,0 +1,76 @@ |
|||||||
|
#include "common/ISegmentStream.h" |
||||||
|
|
||||||
|
ISegmentStream::ISegmentStream() |
||||||
|
{ |
||||||
|
streamLength = 0; |
||||||
|
} |
||||||
|
|
||||||
|
ISegmentStream::~ISegmentStream() |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void ISegmentStream::AttachStream(IDataStream * inStream) |
||||||
|
{ |
||||||
|
parent = inStream; |
||||||
|
streamLength = 0; |
||||||
|
streamOffset = 0; |
||||||
|
} |
||||||
|
|
||||||
|
void ISegmentStream::AddSegment(UInt64 offset, UInt64 length, UInt64 parentOffset) |
||||||
|
{ |
||||||
|
segmentInfo.push_back(SegmentInfo(offset, length, parentOffset)); |
||||||
|
|
||||||
|
if(streamLength < (parentOffset + length)) |
||||||
|
streamLength = parentOffset + length; |
||||||
|
} |
||||||
|
|
||||||
|
void ISegmentStream::ReadBuf(void * buf, UInt32 inLength) |
||||||
|
{ |
||||||
|
UInt32 remain = inLength; |
||||||
|
UInt8 * out = (UInt8 *)buf; |
||||||
|
|
||||||
|
while(remain > 0) |
||||||
|
{ |
||||||
|
SegmentInfo * info = LookupInfo(streamOffset); |
||||||
|
ASSERT(info); |
||||||
|
|
||||||
|
UInt64 segmentOffset = streamOffset - info->offset; |
||||||
|
UInt64 transferLength = info->length - segmentOffset; |
||||||
|
|
||||||
|
if(transferLength > remain) |
||||||
|
transferLength = remain; |
||||||
|
|
||||||
|
parent->SetOffset(info->parentOffset + segmentOffset); |
||||||
|
parent->ReadBuf(out, transferLength); |
||||||
|
|
||||||
|
streamOffset += transferLength; |
||||||
|
remain -= transferLength; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ISegmentStream::WriteBuf(const void * buf, UInt32 inLength) |
||||||
|
{ |
||||||
|
HALT("ISegmentStream::WriteBuf: writing unsupported"); |
||||||
|
} |
||||||
|
|
||||||
|
void ISegmentStream::SetOffset(SInt64 inOffset) |
||||||
|
{ |
||||||
|
SegmentInfo * info = LookupInfo(inOffset); |
||||||
|
ASSERT(info); |
||||||
|
|
||||||
|
UInt64 segmentOffset = inOffset - info->offset; |
||||||
|
|
||||||
|
parent->SetOffset(info->parentOffset + segmentOffset); |
||||||
|
|
||||||
|
streamOffset = inOffset; |
||||||
|
} |
||||||
|
|
||||||
|
ISegmentStream::SegmentInfo * ISegmentStream::LookupInfo(UInt64 offset) |
||||||
|
{ |
||||||
|
for(SegmentInfoListType::iterator iter = segmentInfo.begin(); iter != segmentInfo.end(); iter++) |
||||||
|
if((offset >= (*iter).offset) && (offset < (*iter).offset + (*iter).length)) |
||||||
|
return &(*iter); |
||||||
|
|
||||||
|
return NULL; |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/IDataStream.h" |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
/**
|
||||||
|
* An stream composed of many non-contiguous segments of a larger stream |
||||||
|
*/ |
||||||
|
class ISegmentStream : public IDataStream |
||||||
|
{ |
||||||
|
public: |
||||||
|
ISegmentStream(); |
||||||
|
~ISegmentStream(); |
||||||
|
|
||||||
|
void AttachStream(IDataStream * inStream); |
||||||
|
|
||||||
|
void AddSegment(UInt64 offset, UInt64 length, UInt64 parentOffset); |
||||||
|
|
||||||
|
virtual void ReadBuf(void * buf, UInt32 inLength); |
||||||
|
virtual void WriteBuf(const void * buf, UInt32 inLength); |
||||||
|
virtual void SetOffset(SInt64 inOffset); |
||||||
|
|
||||||
|
protected: |
||||||
|
IDataStream * parent; |
||||||
|
|
||||||
|
struct SegmentInfo |
||||||
|
{ |
||||||
|
SegmentInfo(UInt64 inOffset, UInt64 inLength, UInt64 inParentOffset) |
||||||
|
{ |
||||||
|
offset = inOffset; |
||||||
|
length = inLength; |
||||||
|
parentOffset = inParentOffset; |
||||||
|
} |
||||||
|
|
||||||
|
UInt64 offset; |
||||||
|
UInt64 length; |
||||||
|
UInt64 parentOffset; |
||||||
|
}; |
||||||
|
|
||||||
|
typedef std::vector <SegmentInfo> SegmentInfoListType; |
||||||
|
SegmentInfoListType segmentInfo; |
||||||
|
|
||||||
|
SegmentInfo * LookupInfo(UInt64 offset); |
||||||
|
}; |
@ -0,0 +1,3 @@ |
|||||||
|
#include "common/ISingleton.h" |
||||||
|
|
||||||
|
//template <typename T> T * Singleton <T>::ms_Singleton = 0;
|
@ -0,0 +1,53 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/IErrors.h" |
||||||
|
|
||||||
|
#pragma warning(push) |
||||||
|
#pragma warning(disable: 4311 4312) |
||||||
|
|
||||||
|
/**
|
||||||
|
* A singleton base class |
||||||
|
*
|
||||||
|
* Singletons are useful when you have a class that will be instantiated once, |
||||||
|
* like a global manager. |
||||||
|
*/ |
||||||
|
template <typename T> |
||||||
|
class ISingleton |
||||||
|
{ |
||||||
|
static T * ms_Singleton; |
||||||
|
|
||||||
|
public: |
||||||
|
ISingleton() |
||||||
|
{ |
||||||
|
ASSERT(!ms_Singleton); |
||||||
|
intptr_t offset = (intptr_t)(T *)1 - (intptr_t)(ISingleton <T> *)(T *)1; |
||||||
|
ms_Singleton = (T *)((intptr_t)this + offset); |
||||||
|
} |
||||||
|
|
||||||
|
virtual ~ISingleton() |
||||||
|
{ |
||||||
|
ASSERT(ms_Singleton); |
||||||
|
ms_Singleton = 0; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the single instance of the derived class |
||||||
|
*/ |
||||||
|
static T& GetSingleton(void) |
||||||
|
{ |
||||||
|
ASSERT(ms_Singleton); |
||||||
|
return *ms_Singleton; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer to the single instance of the derived class |
||||||
|
*/ |
||||||
|
static T * GetSingletonPtr(void) |
||||||
|
{ |
||||||
|
return ms_Singleton; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
template <typename T> T * ISingleton <T>::ms_Singleton = 0; |
||||||
|
|
||||||
|
#pragma warning(pop) |
@ -0,0 +1,83 @@ |
|||||||
|
#include "ITextParser.h" |
||||||
|
#include "IDataStream.h" |
||||||
|
|
||||||
|
ITextParser::ITextParser() |
||||||
|
:m_stream(NULL) |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
ITextParser::ITextParser(IDataStream * stream) |
||||||
|
:m_stream(stream) |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
ITextParser::~ITextParser() |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
void ITextParser::Attach(IDataStream * stream) |
||||||
|
{ |
||||||
|
m_stream = stream; |
||||||
|
} |
||||||
|
|
||||||
|
void ITextParser::SkipWhitespace(void) |
||||||
|
{ |
||||||
|
while(!m_stream->HitEOF()) |
||||||
|
{ |
||||||
|
char data = m_stream->Peek8(); |
||||||
|
|
||||||
|
if(!isspace(data)) |
||||||
|
break; |
||||||
|
|
||||||
|
m_stream->Skip(1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ITextParser::SkipLine(void) |
||||||
|
{ |
||||||
|
while(!m_stream->HitEOF()) |
||||||
|
{ |
||||||
|
char data = m_stream->Peek8(); |
||||||
|
|
||||||
|
if((data != '\n') && (data != '\r')) |
||||||
|
break; |
||||||
|
|
||||||
|
m_stream->Skip(1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ITextParser::ReadLine(char * out, UInt32 length) |
||||||
|
{ |
||||||
|
m_stream->ReadString(out, length, '\n', '\r'); |
||||||
|
} |
||||||
|
|
||||||
|
void ITextParser::ReadToken(char * buf, UInt32 bufLength) |
||||||
|
{ |
||||||
|
char * traverse = buf; |
||||||
|
|
||||||
|
ASSERT_STR(bufLength > 0, "ITextParser::ReadToken: zero-sized buffer"); |
||||||
|
|
||||||
|
if(bufLength == 1) |
||||||
|
{ |
||||||
|
buf[0] = 0; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
bufLength--; |
||||||
|
|
||||||
|
for(UInt32 i = 0; (i < bufLength) && !m_stream->HitEOF(); i++) |
||||||
|
{ |
||||||
|
UInt8 data = m_stream->Read8(); |
||||||
|
|
||||||
|
if(isspace(data) || !data) |
||||||
|
break; |
||||||
|
|
||||||
|
*traverse++ = data; |
||||||
|
} |
||||||
|
|
||||||
|
*traverse++ = 0; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/IDataStream.h" |
||||||
|
|
||||||
|
class ITextParser |
||||||
|
{ |
||||||
|
public: |
||||||
|
ITextParser(); |
||||||
|
ITextParser(IDataStream * stream); |
||||||
|
~ITextParser(); |
||||||
|
|
||||||
|
void Attach(IDataStream * stream); |
||||||
|
IDataStream * GetStream(void) { return m_stream; } |
||||||
|
|
||||||
|
bool HitEOF(void) { return m_stream->HitEOF(); } |
||||||
|
|
||||||
|
void SkipWhitespace(void); |
||||||
|
void SkipLine(void); |
||||||
|
|
||||||
|
void ReadLine(char * out, UInt32 length); |
||||||
|
void ReadToken(char * out, UInt32 length); |
||||||
|
|
||||||
|
private: |
||||||
|
IDataStream * m_stream; |
||||||
|
}; |
@ -0,0 +1,65 @@ |
|||||||
|
#include "IThread.h" |
||||||
|
|
||||||
|
IThread::IThread() |
||||||
|
{ |
||||||
|
mainProc = NULL; |
||||||
|
mainProcParam = NULL; |
||||||
|
stopRequested = false; |
||||||
|
isRunning = false; |
||||||
|
theThread = NULL; |
||||||
|
threadID = 0; |
||||||
|
} |
||||||
|
|
||||||
|
IThread::~IThread() |
||||||
|
{ |
||||||
|
ForceStop(); |
||||||
|
|
||||||
|
if(theThread) |
||||||
|
{ |
||||||
|
CloseHandle(theThread); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void IThread::Start(MainProcPtr proc, void * procParam) |
||||||
|
{ |
||||||
|
if(!isRunning) |
||||||
|
{ |
||||||
|
isRunning = true; |
||||||
|
stopRequested = false; |
||||||
|
|
||||||
|
mainProc = proc; |
||||||
|
mainProcParam = procParam; |
||||||
|
|
||||||
|
theThread = CreateThread(NULL, 0, _ThreadProc, static_cast<IThread *>(this), 0, &threadID); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void IThread::Stop(void) |
||||||
|
{ |
||||||
|
if(isRunning) |
||||||
|
{ |
||||||
|
stopRequested = true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void IThread::ForceStop(void) |
||||||
|
{ |
||||||
|
if(isRunning) |
||||||
|
{ |
||||||
|
TerminateThread(theThread, 0); |
||||||
|
|
||||||
|
isRunning = false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
UInt32 IThread::_ThreadProc(void * param) |
||||||
|
{ |
||||||
|
IThread * _this = (IThread *)param; |
||||||
|
|
||||||
|
if(_this->mainProc) |
||||||
|
_this->mainProc(_this->mainProcParam); |
||||||
|
|
||||||
|
_this->isRunning = false; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
// TODO: I really don't like the interface for this
|
||||||
|
|
||||||
|
class IThread |
||||||
|
{ |
||||||
|
public: |
||||||
|
typedef void (* MainProcPtr)(void * param); |
||||||
|
|
||||||
|
IThread(); |
||||||
|
~IThread(); |
||||||
|
|
||||||
|
void Start(MainProcPtr proc, void * procParam = NULL); |
||||||
|
void Stop(void); |
||||||
|
void ForceStop(void); |
||||||
|
|
||||||
|
bool IsRunning(void) { return isRunning; } |
||||||
|
bool StopRequested(void) { return stopRequested; } |
||||||
|
|
||||||
|
HANDLE GetHandle(void) { return theThread; } |
||||||
|
|
||||||
|
protected: |
||||||
|
MainProcPtr mainProc; |
||||||
|
void * mainProcParam; |
||||||
|
volatile bool stopRequested; |
||||||
|
bool isRunning; |
||||||
|
HANDLE theThread; |
||||||
|
UInt32 threadID; |
||||||
|
|
||||||
|
private: |
||||||
|
static UInt32 WINAPI _ThreadProc(void * param); |
||||||
|
}; |
@ -0,0 +1,133 @@ |
|||||||
|
#include "ITimer.h" |
||||||
|
|
||||||
|
// QueryPerformanceCounter is very accurate, but hardware bugs can cause it to return inaccurate results
|
||||||
|
// this code uses multimedia timers to check for glitches in QPC
|
||||||
|
|
||||||
|
double ITimer::s_secondsPerCount = 0; |
||||||
|
TIMECAPS ITimer::s_timecaps = { 0 }; |
||||||
|
bool ITimer::s_setTime = false; |
||||||
|
UInt64 ITimer::s_lastQPC = 0; |
||||||
|
UInt64 ITimer::s_qpcWrapMargin = 0; |
||||||
|
bool ITimer::s_hasLastQPC = false; |
||||||
|
UInt32 ITimer::s_qpcWrapCount = 0; |
||||||
|
UInt32 ITimer::s_qpcInaccurateCount = 0; |
||||||
|
|
||||||
|
ITimer::ITimer() |
||||||
|
:m_qpcBase(0), m_tickBase(0) |
||||||
|
{ |
||||||
|
Init(); |
||||||
|
} |
||||||
|
|
||||||
|
ITimer::~ITimer() |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void ITimer::Init(void) |
||||||
|
{ |
||||||
|
if(!s_secondsPerCount) |
||||||
|
{ |
||||||
|
// init qpc
|
||||||
|
UInt64 countsPerSecond; |
||||||
|
BOOL res = QueryPerformanceFrequency((LARGE_INTEGER *)&countsPerSecond); |
||||||
|
|
||||||
|
ASSERT_STR(res, "ITimer: no high-resolution timer support"); |
||||||
|
|
||||||
|
s_secondsPerCount = 1.0 / countsPerSecond; |
||||||
|
|
||||||
|
s_qpcWrapMargin = (UInt64)(-((SInt64)(countsPerSecond * 60))); // detect if we've wrapped around by a delta greater than this - also limits max time
|
||||||
|
_MESSAGE("s_qpcWrapMargin: %016I64X", s_qpcWrapMargin); |
||||||
|
_MESSAGE("wrap time: %fs", ((double)0xFFFFFFFFFFFFFFFF) * s_secondsPerCount); |
||||||
|
|
||||||
|
// init multimedia timer
|
||||||
|
timeGetDevCaps(&s_timecaps, sizeof(s_timecaps)); |
||||||
|
|
||||||
|
_MESSAGE("min timer period = %d", s_timecaps.wPeriodMin); |
||||||
|
|
||||||
|
s_setTime = (timeBeginPeriod(s_timecaps.wPeriodMin) == TIMERR_NOERROR); |
||||||
|
if(!s_setTime) |
||||||
|
_WARNING("couldn't change timer period"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ITimer::DeInit(void) |
||||||
|
{ |
||||||
|
if(s_secondsPerCount) |
||||||
|
{ |
||||||
|
if(s_setTime) |
||||||
|
{ |
||||||
|
timeEndPeriod(s_timecaps.wPeriodMin); |
||||||
|
s_setTime = false; |
||||||
|
} |
||||||
|
|
||||||
|
if(s_qpcWrapCount) |
||||||
|
_MESSAGE("s_qpcWrapCount: %d", s_qpcWrapCount); |
||||||
|
|
||||||
|
s_secondsPerCount = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ITimer::Start(void) |
||||||
|
{ |
||||||
|
m_qpcBase = GetQPC(); |
||||||
|
m_tickBase = timeGetTime(); |
||||||
|
} |
||||||
|
|
||||||
|
double ITimer::GetElapsedTime(void) |
||||||
|
{ |
||||||
|
UInt64 qpcNow = GetQPC(); |
||||||
|
UInt32 tickNow = timeGetTime(); |
||||||
|
|
||||||
|
UInt64 qpcDelta = qpcNow - m_qpcBase; |
||||||
|
UInt64 tickDelta = tickNow - m_tickBase; |
||||||
|
|
||||||
|
double qpcSeconds = ((double)qpcDelta) * s_secondsPerCount; |
||||||
|
double tickSeconds = ((double)tickDelta) * 0.001; // ticks are in milliseconds
|
||||||
|
double qpcTickDelta = qpcSeconds - tickSeconds; |
||||||
|
|
||||||
|
if(qpcTickDelta < 0) qpcTickDelta = -qpcTickDelta; |
||||||
|
|
||||||
|
// if they differ by more than one second, something's wrong, return
|
||||||
|
if(qpcTickDelta > 1) |
||||||
|
{ |
||||||
|
s_qpcInaccurateCount++; |
||||||
|
return tickSeconds; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return qpcSeconds; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
UInt64 ITimer::GetQPC(void) |
||||||
|
{ |
||||||
|
UInt64 now; |
||||||
|
|
||||||
|
QueryPerformanceCounter((LARGE_INTEGER *)&now); |
||||||
|
|
||||||
|
if(s_hasLastQPC) |
||||||
|
{ |
||||||
|
UInt64 delta = now - s_lastQPC; |
||||||
|
|
||||||
|
if(delta > s_qpcWrapMargin) |
||||||
|
{ |
||||||
|
// we've gone back in time, return a kludged value
|
||||||
|
|
||||||
|
s_lastQPC = now; |
||||||
|
now = s_lastQPC + 1; |
||||||
|
|
||||||
|
s_qpcWrapCount++; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
s_lastQPC = now; |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
s_hasLastQPC = true; |
||||||
|
s_lastQPC = now; |
||||||
|
} |
||||||
|
|
||||||
|
return now; |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/ITypes.h" |
||||||
|
|
||||||
|
/**
|
||||||
|
* A high-resolution timer. |
||||||
|
*/ |
||||||
|
class ITimer |
||||||
|
{ |
||||||
|
public: |
||||||
|
ITimer(); |
||||||
|
~ITimer(); |
||||||
|
|
||||||
|
static void Init(void); |
||||||
|
static void DeInit(void); |
||||||
|
|
||||||
|
void Start(void); |
||||||
|
|
||||||
|
double GetElapsedTime(void); // seconds
|
||||||
|
|
||||||
|
private: |
||||||
|
UInt64 m_qpcBase; // QPC
|
||||||
|
UInt32 m_tickBase; // timeGetTime
|
||||||
|
|
||||||
|
static double s_secondsPerCount; |
||||||
|
static TIMECAPS s_timecaps; |
||||||
|
static bool s_setTime; |
||||||
|
|
||||||
|
// safe QPC stuff
|
||||||
|
static UInt64 GetQPC(void); |
||||||
|
|
||||||
|
static UInt64 s_lastQPC; |
||||||
|
static UInt64 s_qpcWrapMargin; |
||||||
|
static bool s_hasLastQPC; |
||||||
|
|
||||||
|
static UInt32 s_qpcWrapCount; |
||||||
|
static UInt32 s_qpcInaccurateCount; |
||||||
|
}; |
@ -0,0 +1,66 @@ |
|||||||
|
#include "ITypes.h" |
||||||
|
|
||||||
|
Bitstring::Bitstring() |
||||||
|
:data(NULL) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
Bitstring::Bitstring(UInt32 inLength) |
||||||
|
:data(NULL) |
||||||
|
{ |
||||||
|
Alloc(inLength); |
||||||
|
} |
||||||
|
|
||||||
|
Bitstring::~Bitstring() |
||||||
|
{ |
||||||
|
Dispose(); |
||||||
|
} |
||||||
|
|
||||||
|
void Bitstring::Alloc(UInt32 inLength) |
||||||
|
{ |
||||||
|
Dispose(); |
||||||
|
|
||||||
|
inLength = (inLength + 7) & ~7; |
||||||
|
length = inLength >> 3; |
||||||
|
|
||||||
|
data = new UInt8[length]; |
||||||
|
} |
||||||
|
|
||||||
|
void Bitstring::Dispose(void) |
||||||
|
{ |
||||||
|
delete [] data; |
||||||
|
} |
||||||
|
|
||||||
|
void Bitstring::Clear(void) |
||||||
|
{ |
||||||
|
std::memset(data, 0, length); |
||||||
|
} |
||||||
|
|
||||||
|
void Bitstring::Clear(UInt32 idx) |
||||||
|
{ |
||||||
|
ASSERT_STR(idx < (length << 3), "Bitstring::Clear: out of range"); |
||||||
|
|
||||||
|
data[idx >> 3] &= ~(1 << (idx & 7)); |
||||||
|
} |
||||||
|
|
||||||
|
void Bitstring::Set(UInt32 idx) |
||||||
|
{ |
||||||
|
ASSERT_STR(idx < (length << 3), "Bitstring::Set: out of range"); |
||||||
|
|
||||||
|
data[idx >> 3] |= (1 << (idx & 7)); |
||||||
|
} |
||||||
|
|
||||||
|
bool Bitstring::IsSet(UInt32 idx) |
||||||
|
{ |
||||||
|
ASSERT_STR(idx < (length << 3), "Bitstring::IsSet: out of range"); |
||||||
|
|
||||||
|
return (data[idx >> 3] & (1 << (idx & 7))) ? true : false; |
||||||
|
} |
||||||
|
|
||||||
|
bool Bitstring::IsClear(UInt32 idx) |
||||||
|
{ |
||||||
|
ASSERT_STR(idx < (length << 3), "Bitstring::IsClear: out of range"); |
||||||
|
|
||||||
|
return (data[idx >> 3] & (1 << (idx & 7))) ? false : true; |
||||||
|
} |
@ -0,0 +1,344 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/IErrors.h" |
||||||
|
|
||||||
|
#pragma warning(disable: 4221) |
||||||
|
#include <cmath> |
||||||
|
|
||||||
|
typedef unsigned char UInt8; //!< An unsigned 8-bit integer value
|
||||||
|
typedef unsigned short UInt16; //!< An unsigned 16-bit integer value
|
||||||
|
typedef unsigned long UInt32; //!< An unsigned 32-bit integer value
|
||||||
|
typedef unsigned long long UInt64; //!< An unsigned 64-bit integer value
|
||||||
|
typedef signed char SInt8; //!< A signed 8-bit integer value
|
||||||
|
typedef signed short SInt16; //!< A signed 16-bit integer value
|
||||||
|
typedef signed long SInt32; //!< A signed 32-bit integer value
|
||||||
|
typedef signed long long SInt64; //!< A signed 64-bit integer value
|
||||||
|
typedef float Float32; //!< A 32-bit floating point value
|
||||||
|
typedef double Float64; //!< A 64-bit floating point value
|
||||||
|
|
||||||
|
inline UInt32 Extend16(UInt32 in) |
||||||
|
{ |
||||||
|
return (in & 0x8000) ? (0xFFFF0000 | in) : in; |
||||||
|
} |
||||||
|
|
||||||
|
inline UInt32 Extend8(UInt32 in) |
||||||
|
{ |
||||||
|
return (in & 0x80) ? (0xFFFFFF00 | in) : in; |
||||||
|
} |
||||||
|
|
||||||
|
inline UInt16 Swap16(UInt16 in) |
||||||
|
{ |
||||||
|
return ((in >> 8) & 0x00FF) | |
||||||
|
((in << 8) & 0xFF00); |
||||||
|
} |
||||||
|
|
||||||
|
inline UInt32 Swap32(UInt32 in) |
||||||
|
{ |
||||||
|
return ((in >> 24) & 0x000000FF) | |
||||||
|
((in >> 8) & 0x0000FF00) | |
||||||
|
((in << 8) & 0x00FF0000) | |
||||||
|
((in << 24) & 0xFF000000); |
||||||
|
} |
||||||
|
|
||||||
|
inline UInt64 Swap64(UInt64 in) |
||||||
|
{ |
||||||
|
UInt64 temp; |
||||||
|
|
||||||
|
temp = Swap32(in); |
||||||
|
temp <<= 32; |
||||||
|
temp |= Swap32(in >> 32); |
||||||
|
|
||||||
|
return temp; |
||||||
|
} |
||||||
|
|
||||||
|
inline void SwapFloat(float * in) |
||||||
|
{ |
||||||
|
UInt32 * temp = (UInt32 *)in; |
||||||
|
|
||||||
|
*temp = Swap32(*temp); |
||||||
|
} |
||||||
|
|
||||||
|
inline void SwapDouble(double * in) |
||||||
|
{ |
||||||
|
UInt64 * temp = (UInt64 *)in; |
||||||
|
|
||||||
|
*temp = Swap64(*temp); |
||||||
|
} |
||||||
|
|
||||||
|
inline bool IsBigEndian(void) |
||||||
|
{ |
||||||
|
union |
||||||
|
{ |
||||||
|
UInt16 u16; |
||||||
|
UInt8 u8[2]; |
||||||
|
} temp; |
||||||
|
|
||||||
|
temp.u16 = 0x1234; |
||||||
|
|
||||||
|
return temp.u8[0] == 0x12; |
||||||
|
} |
||||||
|
|
||||||
|
inline bool IsLittleEndian(void) |
||||||
|
{ |
||||||
|
return !IsBigEndian(); |
||||||
|
} |
||||||
|
|
||||||
|
#define CHAR_CODE(a, b, c, d) (((a & 0xFF) << 0) | ((b & 0xFF) << 8) | ((c & 0xFF) << 16) | ((d & 0xFF) << 24)) |
||||||
|
#define MACRO_SWAP16(a) ((((a) & 0x00FF) << 8) | (((a) & 0xFF00) >> 8)) |
||||||
|
#define MACRO_SWAP32(a) ((((a) & 0x000000FF) << 24) | (((a) & 0x0000FF00) << 8) | (((a) & 0x00FF0000) >> 8) | (((a) & 0xFF000000) >> 24)) |
||||||
|
|
||||||
|
#define VERSION_CODE(primary, secondary, sub) (((primary & 0xFFF) << 20) | ((secondary & 0xFFF) << 8) | ((sub & 0xFF) << 0)) |
||||||
|
#define VERSION_CODE_PRIMARY(in) ((in >> 20) & 0xFFF) |
||||||
|
#define VERSION_CODE_SECONDARY(in) ((in >> 8) & 0xFFF) |
||||||
|
#define VERSION_CODE_SUB(in) ((in >> 0) & 0xFF) |
||||||
|
|
||||||
|
#define MAKE_COLOR(a, r, g, b) (((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | ((b & 0xFF) << 0)) |
||||||
|
#define COLOR_ALPHA(in) ((in >> 24) & 0xFF) |
||||||
|
#define COLOR_RED(in) ((in >> 16) & 0xFF) |
||||||
|
#define COLOR_GREEN(in) ((in >> 8) & 0xFF) |
||||||
|
#define COLOR_BLUE(in) ((in >> 0) & 0xFF) |
||||||
|
|
||||||
|
/**
|
||||||
|
* A 64-bit variable combiner |
||||||
|
*
|
||||||
|
* Useful for endian-independent value extraction. |
||||||
|
*/ |
||||||
|
union VarCombiner |
||||||
|
{ |
||||||
|
UInt64 u64; |
||||||
|
SInt64 s64; |
||||||
|
double f64; |
||||||
|
struct { UInt32 b; UInt32 a; } u32; |
||||||
|
struct { SInt32 b; SInt32 a; } s32; |
||||||
|
struct { float b; float a; } f32; |
||||||
|
struct { UInt16 d; UInt16 c; UInt16 b; UInt16 a; } u16; |
||||||
|
struct { SInt16 d; SInt16 c; SInt16 b; SInt16 a; } s16; |
||||||
|
struct { UInt8 h; UInt8 g; UInt8 f; UInt8 e; |
||||||
|
UInt8 d; UInt8 c; UInt8 b; UInt8 a; } u8; |
||||||
|
struct { SInt8 h; SInt8 g; SInt8 f; SInt8 e; |
||||||
|
SInt8 d; SInt8 c; SInt8 b; SInt8 a; } s8; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* A bitfield. |
||||||
|
*/ |
||||||
|
template <typename T> |
||||||
|
class Bitfield |
||||||
|
{ |
||||||
|
public: |
||||||
|
Bitfield() { } |
||||||
|
~Bitfield() { } |
||||||
|
|
||||||
|
void Clear(void) { field = 0; } //!< Clears all bits
|
||||||
|
void RawSet(UInt32 data) { field = data; } //!< Modifies all bits
|
||||||
|
|
||||||
|
void Set(UInt32 data) { field |= data; } //!< Sets individual bits
|
||||||
|
void Clear(UInt32 data) { field &= ~data; } //!< Clears individual bits
|
||||||
|
void UnSet(UInt32 data) { Clear(data); } //!< Clears individual bits
|
||||||
|
void Mask(UInt32 data) { field &= data; } //!< Masks individual bits
|
||||||
|
void Toggle(UInt32 data) { field ^= data; } //!< Toggles individual bits
|
||||||
|
void Write(UInt32 data, bool state) |
||||||
|
{ if(state) Set(data); else Clear(data); } |
||||||
|
|
||||||
|
T Get(void) const { return field; } //!< Gets all bits
|
||||||
|
T Get(UInt32 data) const { return field & data; } //!< Gets individual bits
|
||||||
|
T Extract(UInt32 bit) const { return (field >> bit) & 1; } //!< Extracts a bit
|
||||||
|
T ExtractField(UInt32 shift, UInt32 length) //!< Extracts a series of bits
|
||||||
|
{ return (field >> shift) & (0xFFFFFFFF >> (32 - length)); } |
||||||
|
|
||||||
|
bool IsSet(UInt32 data) const { return ((field & data) == data) ? true : false; } //!< Are all these bits set?
|
||||||
|
bool IsUnSet(UInt32 data) const { return (field & data) ? false : true; } //!< Are all these bits clear?
|
||||||
|
bool IsClear(UInt32 data) const { return IsUnSet(data); } //!< Are all these bits clear?
|
||||||
|
|
||||||
|
private: |
||||||
|
T field; //!< bitfield data
|
||||||
|
}; |
||||||
|
|
||||||
|
typedef Bitfield <UInt8> Bitfield8; //!< An 8-bit bitfield
|
||||||
|
typedef Bitfield <UInt16> Bitfield16; //!< A 16-bit bitfield
|
||||||
|
typedef Bitfield <UInt32> Bitfield32; //!< A 32-bit bitfield
|
||||||
|
|
||||||
|
STATIC_ASSERT(sizeof(Bitfield8) == 1); |
||||||
|
STATIC_ASSERT(sizeof(Bitfield16) == 2); |
||||||
|
STATIC_ASSERT(sizeof(Bitfield32) == 4); |
||||||
|
|
||||||
|
/**
|
||||||
|
* A bitstring |
||||||
|
*
|
||||||
|
* Essentially a long bitvector. |
||||||
|
*/ |
||||||
|
class Bitstring |
||||||
|
{ |
||||||
|
public: |
||||||
|
Bitstring(); |
||||||
|
Bitstring(UInt32 inLength); |
||||||
|
~Bitstring(); |
||||||
|
|
||||||
|
void Alloc(UInt32 inLength); |
||||||
|
void Dispose(void); |
||||||
|
|
||||||
|
void Clear(void); |
||||||
|
void Clear(UInt32 idx); |
||||||
|
void Set(UInt32 idx); |
||||||
|
|
||||||
|
bool IsSet(UInt32 idx); |
||||||
|
bool IsClear(UInt32 idx); |
||||||
|
|
||||||
|
private: |
||||||
|
UInt8 * data; |
||||||
|
UInt32 length; //!< length in bytes
|
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Time storage |
||||||
|
*/ |
||||||
|
class Time |
||||||
|
{ |
||||||
|
public: |
||||||
|
Time() { Clear(); } |
||||||
|
~Time() { } |
||||||
|
|
||||||
|
//! Deinitialize the class
|
||||||
|
void Clear(void) { seconds = minutes = hours = 0; hasData = false; } |
||||||
|
//! Sets the class to the current time
|
||||||
|
//! @todo implement this
|
||||||
|
void SetToNow(void) { Set(1, 2, 3); } |
||||||
|
|
||||||
|
//! Sets the class to the specified time
|
||||||
|
void Set(UInt8 inS, UInt8 inM, UInt8 inH) |
||||||
|
{ seconds = inS; minutes = inM; hours = inH; hasData = true; } |
||||||
|
|
||||||
|
//! Gets whether the class has been initialized or not
|
||||||
|
bool IsSet(void) { return hasData; } |
||||||
|
|
||||||
|
UInt8 GetSeconds(void) { return seconds; } //!< return the seconds portion of the time
|
||||||
|
UInt8 GetMinutes(void) { return minutes; } //!< return the minutes portion of the time
|
||||||
|
UInt8 GetHours(void) { return hours; } //!< return the hours portion of the time
|
||||||
|
|
||||||
|
private: |
||||||
|
UInt8 seconds, minutes, hours; |
||||||
|
bool hasData; |
||||||
|
}; |
||||||
|
|
||||||
|
const float kFloatEpsilon = 0.0001f; |
||||||
|
|
||||||
|
inline bool FloatEqual(float a, float b) { float magnitude = a - b; if(magnitude < 0) magnitude = -magnitude; return magnitude < kFloatEpsilon; } |
||||||
|
|
||||||
|
class Vector2 |
||||||
|
{ |
||||||
|
public: |
||||||
|
Vector2() { } |
||||||
|
Vector2(const Vector2 & in) { x = in.x; y = in.y; } |
||||||
|
Vector2(float inX, float inY) { x = inX; y = inY; } |
||||||
|
~Vector2() { } |
||||||
|
|
||||||
|
void Set(float inX, float inY) { x = inX; y = inY; } |
||||||
|
void SetX(float inX) { x = inX; } |
||||||
|
void SetY(float inY) { y = inY; } |
||||||
|
void Get(float * outX, float * outY) { *outX = x; *outY = y; } |
||||||
|
float GetX(void) { return x; } |
||||||
|
float GetY(void) { return y; } |
||||||
|
|
||||||
|
void Normalize(void) { float mag = Magnitude(); x /= mag; y /= mag; } |
||||||
|
float Magnitude(void) { return sqrt(x*x + y*y); } |
||||||
|
|
||||||
|
void Reverse(void) { float temp = -x; x = -y; y = temp; } |
||||||
|
|
||||||
|
void Scale(float scale) { x *= scale; y *= scale; } |
||||||
|
|
||||||
|
void SwapBytes(void) { SwapFloat(&x); SwapFloat(&y); } |
||||||
|
|
||||||
|
Vector2 & operator+=(const Vector2 & rhs) { x += rhs.x; y += rhs.y; return *this; } |
||||||
|
Vector2 & operator-=(const Vector2 & rhs) { x -= rhs.x; y -= rhs.y; return *this; } |
||||||
|
Vector2 & operator*=(float rhs) { x *= rhs; y *= rhs; return *this; } |
||||||
|
Vector2 & operator/=(float rhs) { x /= rhs; y /= rhs; return *this; } |
||||||
|
|
||||||
|
float x; |
||||||
|
float y; |
||||||
|
}; |
||||||
|
|
||||||
|
inline Vector2 operator+(const Vector2 & lhs, const Vector2 & rhs) |
||||||
|
{ |
||||||
|
return Vector2(lhs.x + rhs.x, lhs.y + rhs.y); |
||||||
|
}; |
||||||
|
|
||||||
|
inline Vector2 operator-(const Vector2 & lhs, const Vector2 & rhs) |
||||||
|
{ |
||||||
|
return Vector2(lhs.x - rhs.x, lhs.y - rhs.y); |
||||||
|
}; |
||||||
|
|
||||||
|
inline Vector2 operator*(const Vector2 & lhs, float rhs) |
||||||
|
{ |
||||||
|
return Vector2(lhs.x * rhs, lhs.y * rhs); |
||||||
|
}; |
||||||
|
|
||||||
|
inline Vector2 operator/(const Vector2 & lhs, float rhs) |
||||||
|
{ |
||||||
|
return Vector2(lhs.x / rhs, lhs.y / rhs); |
||||||
|
}; |
||||||
|
|
||||||
|
inline bool MaskCompare(void * lhs, void * rhs, void * mask, UInt32 size) |
||||||
|
{ |
||||||
|
UInt8 * lhs8 = (UInt8 *)lhs; |
||||||
|
UInt8 * rhs8 = (UInt8 *)rhs; |
||||||
|
UInt8 * mask8 = (UInt8 *)mask; |
||||||
|
|
||||||
|
for(UInt32 i = 0; i < size; i++) |
||||||
|
if((lhs8[i] & mask8[i]) != (rhs8[i] & mask8[i])) |
||||||
|
return false; |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
class Vector3 |
||||||
|
{ |
||||||
|
public: |
||||||
|
Vector3() { } |
||||||
|
Vector3(const Vector3 & in) { x = in.x; y = in.y; z = in.z; } |
||||||
|
Vector3(float inX, float inY, float inZ) { x = inX; y = inY; z = inZ; } |
||||||
|
~Vector3() { } |
||||||
|
|
||||||
|
void Set(float inX, float inY, float inZ) { x = inX; y = inY; z = inZ; } |
||||||
|
void Get(float * outX, float * outY, float * outZ) { *outX = x; *outY = y; *outZ = z; } |
||||||
|
|
||||||
|
void Normalize(void) { float mag = Magnitude(); x /= mag; y /= mag; z /= mag; } |
||||||
|
float Magnitude(void) { return sqrt(x*x + y*y + z*z); } |
||||||
|
|
||||||
|
void Scale(float scale) { x *= scale; y *= scale; z *= scale; } |
||||||
|
|
||||||
|
void SwapBytes(void) { SwapFloat(&x); SwapFloat(&y); SwapFloat(&z); } |
||||||
|
|
||||||
|
Vector3 & operator+=(const Vector3 & rhs) { x += rhs.x; y += rhs.y; z += rhs.z; return *this; } |
||||||
|
Vector3 & operator-=(const Vector3 & rhs) { x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this; } |
||||||
|
Vector3 & operator*=(const Vector3 & rhs) { x *= rhs.x; y *= rhs.y; z *= rhs.z; return *this; } |
||||||
|
Vector3 & operator/=(const Vector3 & rhs) { x /= rhs.x; y /= rhs.y; z /= rhs.z; return *this; } |
||||||
|
|
||||||
|
union |
||||||
|
{ |
||||||
|
struct |
||||||
|
{ |
||||||
|
float x, y, z; |
||||||
|
}; |
||||||
|
float d[3]; |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
inline Vector3 operator+(const Vector3 & lhs, const Vector3 & rhs) |
||||||
|
{ |
||||||
|
return Vector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); |
||||||
|
} |
||||||
|
|
||||||
|
inline Vector3 operator-(const Vector3 & lhs, const Vector3 & rhs) |
||||||
|
{ |
||||||
|
return Vector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); |
||||||
|
} |
||||||
|
|
||||||
|
inline Vector3 operator*(const Vector3 & lhs, const Vector3 & rhs) |
||||||
|
{ |
||||||
|
return Vector3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); |
||||||
|
} |
||||||
|
|
||||||
|
inline Vector3 operator/(const Vector3 & lhs, const Vector3 & rhs) |
||||||
|
{ |
||||||
|
return Vector3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); |
||||||
|
} |
@ -0,0 +1,419 @@ |
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?> |
||||||
|
<VisualStudioProject |
||||||
|
ProjectType="Visual C++" |
||||||
|
Version="8.00" |
||||||
|
Name="common" |
||||||
|
ProjectGUID="{20C6411C-596F-4B85-BE4E-8BC91F59D8A6}" |
||||||
|
RootNamespace="common" |
||||||
|
SccProjectName="Perforce Project" |
||||||
|
SccLocalPath="." |
||||||
|
SccProvider="MSSCCI:Perforce SCM" |
||||||
|
Keyword="Win32Proj" |
||||||
|
> |
||||||
|
<Platforms> |
||||||
|
<Platform |
||||||
|
Name="Win32" |
||||||
|
/> |
||||||
|
</Platforms> |
||||||
|
<ToolFiles> |
||||||
|
</ToolFiles> |
||||||
|
<Configurations> |
||||||
|
<Configuration |
||||||
|
Name="Debug|Win32" |
||||||
|
OutputDirectory="Debug" |
||||||
|
IntermediateDirectory="Debug" |
||||||
|
ConfigurationType="4" |
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" |
||||||
|
CharacterSet="2" |
||||||
|
> |
||||||
|
<Tool |
||||||
|
Name="VCPreBuildEventTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCCustomBuildTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCXMLDataGeneratorTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCWebServiceProxyGeneratorTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCMIDLTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCCLCompilerTool" |
||||||
|
Optimization="0" |
||||||
|
AdditionalIncludeDirectories="$(SolutionDir);$(SolutionDir)\.." |
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS" |
||||||
|
MinimalRebuild="true" |
||||||
|
BasicRuntimeChecks="3" |
||||||
|
RuntimeLibrary="1" |
||||||
|
RuntimeTypeInfo="true" |
||||||
|
UsePrecompiledHeader="0" |
||||||
|
PrecompiledHeaderThrough="" |
||||||
|
WarningLevel="3" |
||||||
|
Detect64BitPortabilityProblems="false" |
||||||
|
DebugInformationFormat="4" |
||||||
|
ForcedIncludeFiles="common/IPrefix.h" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCManagedResourceCompilerTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCResourceCompilerTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCPreLinkEventTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCLibrarianTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCALinkTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCXDCMakeTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCBscMakeTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCFxCopTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCPostBuildEventTool" |
||||||
|
/> |
||||||
|
</Configuration> |
||||||
|
<Configuration |
||||||
|
Name="Release|Win32" |
||||||
|
OutputDirectory="Release" |
||||||
|
IntermediateDirectory="Release" |
||||||
|
ConfigurationType="4" |
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" |
||||||
|
CharacterSet="2" |
||||||
|
> |
||||||
|
<Tool |
||||||
|
Name="VCPreBuildEventTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCCustomBuildTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCXMLDataGeneratorTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCWebServiceProxyGeneratorTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCMIDLTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCCLCompilerTool" |
||||||
|
AdditionalIncludeDirectories="$(SolutionDir);$(SolutionDir)\.." |
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS" |
||||||
|
RuntimeLibrary="0" |
||||||
|
RuntimeTypeInfo="true" |
||||||
|
UsePrecompiledHeader="0" |
||||||
|
PrecompiledHeaderThrough="" |
||||||
|
WarningLevel="3" |
||||||
|
Detect64BitPortabilityProblems="false" |
||||||
|
DebugInformationFormat="3" |
||||||
|
ForcedIncludeFiles="common/IPrefix.h" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCManagedResourceCompilerTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCResourceCompilerTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCPreLinkEventTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCLibrarianTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCALinkTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCXDCMakeTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCBscMakeTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCFxCopTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCPostBuildEventTool" |
||||||
|
/> |
||||||
|
</Configuration> |
||||||
|
</Configurations> |
||||||
|
<References> |
||||||
|
</References> |
||||||
|
<Files> |
||||||
|
<Filter |
||||||
|
Name="streams" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IBufferStream.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IBufferStream.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDataStream.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDataStream.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IFileStream.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IFileStream.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ISegmentStream.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ISegmentStream.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="debug" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IDebugLog.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDebugLog.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath="IErrors.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath="IErrors.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="threads" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\ICriticalSection.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IEvent.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IEvent.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IInterlockedLong.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IInterlockedLong.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IMutex.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IMutex.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IReadWriteLock.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IReadWriteLock.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IThread.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IThread.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="datatypes" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IArchive.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IArchive.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDatabase.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDatabase.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDatabase.inc" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IFIFO.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IFIFO.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ILinkedList.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IRangeMap.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IRangeMap.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ISingleton.cpp" |
||||||
|
> |
||||||
|
<FileConfiguration |
||||||
|
Name="Debug|Win32" |
||||||
|
ExcludedFromBuild="true" |
||||||
|
> |
||||||
|
<Tool |
||||||
|
Name="VCCLCompilerTool" |
||||||
|
/> |
||||||
|
</FileConfiguration> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath="ISingleton.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITextParser.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITextParser.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITypes.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITypes.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="utilities" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath="IConsole.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath="IConsole.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDynamicCreate.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDynamicCreate.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITimer.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITimer.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="memory" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IMemPool.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IMemPool.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="pipe" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IPipeClient.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IPipeClient.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IPipeServer.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IPipeServer.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="files" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IDirectoryIterator.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDirectoryIterator.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<File |
||||||
|
RelativePath=".\IPrefix.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IPrefix.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Files> |
||||||
|
<Globals> |
||||||
|
</Globals> |
||||||
|
</VisualStudioProject> |
@ -0,0 +1,22 @@ |
|||||||
|
This license applies to all of the files in src/common: |
||||||
|
|
||||||
|
Copyright (c) 2006-2011 Ian Patterson |
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied |
||||||
|
warranty. In no event will the authors be held liable for any damages |
||||||
|
arising from the use of this software. |
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose, |
||||||
|
including commercial applications, and to alter it and redistribute it |
||||||
|
freely, subject to the following restrictions: |
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not |
||||||
|
claim that you wrote the original software. If you use this software |
||||||
|
in a product, an acknowledgment in the product documentation would be |
||||||
|
appreciated but is not required. |
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be |
||||||
|
misrepresented as being the original software. |
||||||
|
|
||||||
|
3. This notice may not be removed or altered from any source |
||||||
|
distribution. |
@ -0,0 +1,418 @@ |
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?> |
||||||
|
<VisualStudioProject |
||||||
|
ProjectType="Visual C++" |
||||||
|
Version="9.00" |
||||||
|
Name="common_vc12" |
||||||
|
ProjectGUID="{20C6411C-596F-4B85-BE4E-8BC91F59D8A6}" |
||||||
|
RootNamespace="common" |
||||||
|
SccProjectName="Perforce Project" |
||||||
|
SccLocalPath="." |
||||||
|
SccProvider="MSSCCI:Perforce SCM" |
||||||
|
Keyword="Win32Proj" |
||||||
|
TargetFrameworkVersion="131072" |
||||||
|
> |
||||||
|
<Platforms> |
||||||
|
<Platform |
||||||
|
Name="Win32" |
||||||
|
/> |
||||||
|
</Platforms> |
||||||
|
<ToolFiles> |
||||||
|
</ToolFiles> |
||||||
|
<Configurations> |
||||||
|
<Configuration |
||||||
|
Name="Debug|Win32" |
||||||
|
OutputDirectory="Debug VC12" |
||||||
|
IntermediateDirectory="Debug VC12" |
||||||
|
ConfigurationType="4" |
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" |
||||||
|
CharacterSet="2" |
||||||
|
> |
||||||
|
<Tool |
||||||
|
Name="VCPreBuildEventTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCCustomBuildTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCXMLDataGeneratorTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCWebServiceProxyGeneratorTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCMIDLTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCCLCompilerTool" |
||||||
|
Optimization="0" |
||||||
|
AdditionalIncludeDirectories=""$(SolutionDir)";"$(SolutionDir)\..";"$(SolutionDir)\..\.."" |
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS" |
||||||
|
MinimalRebuild="true" |
||||||
|
BasicRuntimeChecks="3" |
||||||
|
RuntimeLibrary="1" |
||||||
|
RuntimeTypeInfo="true" |
||||||
|
UsePrecompiledHeader="0" |
||||||
|
PrecompiledHeaderThrough="" |
||||||
|
WarningLevel="3" |
||||||
|
Detect64BitPortabilityProblems="false" |
||||||
|
DebugInformationFormat="4" |
||||||
|
ForcedIncludeFiles="common/IPrefix.h" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCManagedResourceCompilerTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCResourceCompilerTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCPreLinkEventTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCLibrarianTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCALinkTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCXDCMakeTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCBscMakeTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCFxCopTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCPostBuildEventTool" |
||||||
|
/> |
||||||
|
</Configuration> |
||||||
|
<Configuration |
||||||
|
Name="Release|Win32" |
||||||
|
OutputDirectory="Release VC12" |
||||||
|
IntermediateDirectory="Release VC12" |
||||||
|
ConfigurationType="4" |
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" |
||||||
|
CharacterSet="2" |
||||||
|
> |
||||||
|
<Tool |
||||||
|
Name="VCPreBuildEventTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCCustomBuildTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCXMLDataGeneratorTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCWebServiceProxyGeneratorTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCMIDLTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCCLCompilerTool" |
||||||
|
AdditionalIncludeDirectories=""$(SolutionDir)";"$(SolutionDir)\..";"$(SolutionDir)\..\.."" |
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS" |
||||||
|
RuntimeLibrary="0" |
||||||
|
RuntimeTypeInfo="true" |
||||||
|
UsePrecompiledHeader="0" |
||||||
|
PrecompiledHeaderThrough="" |
||||||
|
WarningLevel="3" |
||||||
|
Detect64BitPortabilityProblems="false" |
||||||
|
DebugInformationFormat="3" |
||||||
|
ForcedIncludeFiles="common/IPrefix.h" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCManagedResourceCompilerTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCResourceCompilerTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCPreLinkEventTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCLibrarianTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCALinkTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCXDCMakeTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCBscMakeTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCFxCopTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCPostBuildEventTool" |
||||||
|
/> |
||||||
|
</Configuration> |
||||||
|
</Configurations> |
||||||
|
<References> |
||||||
|
</References> |
||||||
|
<Files> |
||||||
|
<Filter |
||||||
|
Name="streams" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IBufferStream.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IBufferStream.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDataStream.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDataStream.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IFileStream.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IFileStream.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ISegmentStream.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ISegmentStream.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="debug" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IDebugLog.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDebugLog.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath="IErrors.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath="IErrors.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="threads" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\ICriticalSection.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IEvent.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IEvent.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IInterlockedLong.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IInterlockedLong.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IMutex.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IMutex.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IReadWriteLock.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IReadWriteLock.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IThread.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IThread.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="datatypes" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IArchive.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IArchive.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDatabase.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDatabase.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDatabase.inc" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IFIFO.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IFIFO.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ILinkedList.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IRangeMap.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IRangeMap.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ISingleton.cpp" |
||||||
|
> |
||||||
|
<FileConfiguration |
||||||
|
Name="Debug|Win32" |
||||||
|
ExcludedFromBuild="true" |
||||||
|
> |
||||||
|
<Tool |
||||||
|
Name="VCCLCompilerTool" |
||||||
|
/> |
||||||
|
</FileConfiguration> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath="ISingleton.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITextParser.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITextParser.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITypes.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITypes.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="utilities" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath="IConsole.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath="IConsole.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDynamicCreate.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDynamicCreate.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITimer.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITimer.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="memory" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IMemPool.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IMemPool.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="pipe" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IPipeClient.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IPipeClient.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IPipeServer.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IPipeServer.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="files" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IDirectoryIterator.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDirectoryIterator.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<File |
||||||
|
RelativePath=".\IPrefix.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IPrefix.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Files> |
||||||
|
</VisualStudioProject> |
@ -0,0 +1,420 @@ |
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?> |
||||||
|
<VisualStudioProject |
||||||
|
ProjectType="Visual C++" |
||||||
|
Version="9.00" |
||||||
|
Name="common_vc9" |
||||||
|
ProjectGUID="{20C6411C-596F-4B85-BE4E-8BC91F59D8A6}" |
||||||
|
RootNamespace="common" |
||||||
|
SccProjectName="Perforce Project" |
||||||
|
SccLocalPath="." |
||||||
|
SccProvider="MSSCCI:Perforce SCM" |
||||||
|
Keyword="Win32Proj" |
||||||
|
TargetFrameworkVersion="131072" |
||||||
|
> |
||||||
|
<Platforms> |
||||||
|
<Platform |
||||||
|
Name="Win32" |
||||||
|
/> |
||||||
|
</Platforms> |
||||||
|
<ToolFiles> |
||||||
|
</ToolFiles> |
||||||
|
<Configurations> |
||||||
|
<Configuration |
||||||
|
Name="Debug|Win32" |
||||||
|
OutputDirectory="Debug VC9" |
||||||
|
IntermediateDirectory="Debug VC9" |
||||||
|
ConfigurationType="4" |
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" |
||||||
|
CharacterSet="2" |
||||||
|
> |
||||||
|
<Tool |
||||||
|
Name="VCPreBuildEventTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCCustomBuildTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCXMLDataGeneratorTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCWebServiceProxyGeneratorTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCMIDLTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCCLCompilerTool" |
||||||
|
Optimization="0" |
||||||
|
AdditionalIncludeDirectories=""$(SolutionDir)";"$(SolutionDir)\..";"$(SolutionDir)\..\.."" |
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS" |
||||||
|
MinimalRebuild="true" |
||||||
|
BasicRuntimeChecks="3" |
||||||
|
RuntimeLibrary="1" |
||||||
|
RuntimeTypeInfo="true" |
||||||
|
UsePrecompiledHeader="0" |
||||||
|
PrecompiledHeaderThrough="" |
||||||
|
WarningLevel="3" |
||||||
|
Detect64BitPortabilityProblems="false" |
||||||
|
DebugInformationFormat="4" |
||||||
|
ForcedIncludeFiles="common/IPrefix.h" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCManagedResourceCompilerTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCResourceCompilerTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCPreLinkEventTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCLibrarianTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCALinkTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCXDCMakeTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCBscMakeTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCFxCopTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCPostBuildEventTool" |
||||||
|
/> |
||||||
|
</Configuration> |
||||||
|
<Configuration |
||||||
|
Name="Release|Win32" |
||||||
|
OutputDirectory="Release VC9" |
||||||
|
IntermediateDirectory="Release VC9" |
||||||
|
ConfigurationType="4" |
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" |
||||||
|
CharacterSet="2" |
||||||
|
> |
||||||
|
<Tool |
||||||
|
Name="VCPreBuildEventTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCCustomBuildTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCXMLDataGeneratorTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCWebServiceProxyGeneratorTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCMIDLTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCCLCompilerTool" |
||||||
|
AdditionalIncludeDirectories=""$(SolutionDir)";"$(SolutionDir)\..";"$(SolutionDir)\..\.."" |
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS" |
||||||
|
RuntimeLibrary="0" |
||||||
|
RuntimeTypeInfo="true" |
||||||
|
UsePrecompiledHeader="0" |
||||||
|
PrecompiledHeaderThrough="" |
||||||
|
WarningLevel="3" |
||||||
|
Detect64BitPortabilityProblems="false" |
||||||
|
DebugInformationFormat="3" |
||||||
|
ForcedIncludeFiles="common/IPrefix.h" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCManagedResourceCompilerTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCResourceCompilerTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCPreLinkEventTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCLibrarianTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCALinkTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCXDCMakeTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCBscMakeTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCFxCopTool" |
||||||
|
/> |
||||||
|
<Tool |
||||||
|
Name="VCPostBuildEventTool" |
||||||
|
/> |
||||||
|
</Configuration> |
||||||
|
</Configurations> |
||||||
|
<References> |
||||||
|
</References> |
||||||
|
<Files> |
||||||
|
<Filter |
||||||
|
Name="streams" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IBufferStream.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IBufferStream.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDataStream.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDataStream.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IFileStream.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IFileStream.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ISegmentStream.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ISegmentStream.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<Filter |
||||||
|
Name="pipe" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IPipeClient.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IPipeClient.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IPipeServer.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IPipeServer.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="debug" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IDebugLog.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDebugLog.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath="IErrors.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath="IErrors.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="threads" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\ICriticalSection.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IEvent.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IEvent.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IInterlockedLong.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IInterlockedLong.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IMutex.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IMutex.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IReadWriteLock.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IReadWriteLock.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IThread.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IThread.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="datatypes" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IArchive.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IArchive.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDatabase.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDatabase.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDatabase.inc" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IFIFO.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IFIFO.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ILinkedList.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IRangeMap.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IRangeMap.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ISingleton.cpp" |
||||||
|
> |
||||||
|
<FileConfiguration |
||||||
|
Name="Debug|Win32" |
||||||
|
ExcludedFromBuild="true" |
||||||
|
> |
||||||
|
<Tool |
||||||
|
Name="VCCLCompilerTool" |
||||||
|
/> |
||||||
|
</FileConfiguration> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath="ISingleton.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITextParser.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITextParser.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITypes.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITypes.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="utilities" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath="IConsole.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath="IConsole.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDynamicCreate.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDynamicCreate.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITimer.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\ITimer.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="memory" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IMemPool.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IMemPool.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<Filter |
||||||
|
Name="files" |
||||||
|
> |
||||||
|
<File |
||||||
|
RelativePath=".\IDirectoryIterator.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IDirectoryIterator.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Filter> |
||||||
|
<File |
||||||
|
RelativePath=".\IPrefix.cpp" |
||||||
|
> |
||||||
|
</File> |
||||||
|
<File |
||||||
|
RelativePath=".\IPrefix.h" |
||||||
|
> |
||||||
|
</File> |
||||||
|
</Files> |
||||||
|
<Globals> |
||||||
|
</Globals> |
||||||
|
</VisualStudioProject> |
@ -0,0 +1,115 @@ |
|||||||
|
#include "Achievements.h" |
||||||
|
#include "skse64/GameMenus.h" |
||||||
|
#include "skse64/GameEvents.h" |
||||||
|
#include "steam\steam_api.h" |
||||||
|
#include <string> |
||||||
|
#include <processenv.h> |
||||||
|
|
||||||
|
class InitSteamOnEvent : public BSTEventSink<MenuOpenCloseEvent> { |
||||||
|
public: |
||||||
|
virtual ~InitSteamOnEvent() {} |
||||||
|
virtual EventResult ReceiveEvent(MenuOpenCloseEvent * evn, EventDispatcher<MenuOpenCloseEvent> * dispatcher) { |
||||||
|
if (std::strcmp(evn->menuName.data, "Main Menu")) { |
||||||
|
_MESSAGE("Main menu opened, trying to init steam API."); |
||||||
|
Achievements::startSteam(); |
||||||
|
} |
||||||
|
return EventResult::kEvent_Continue; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
namespace Achievements { |
||||||
|
|
||||||
|
bool setAchievementUnlocked(StaticFunctionTag* tag, BSFixedString achievement) |
||||||
|
{ |
||||||
|
return singleton->setAchievementUnlocked(achievement.data); |
||||||
|
} |
||||||
|
|
||||||
|
void registerMainMenuEvent() { |
||||||
|
MenuManager * mm = MenuManager::GetSingleton(); |
||||||
|
if (mm) { |
||||||
|
mm->MenuOpenCloseEventDispatcher()->AddEventSink(new InitSteamOnEvent()); |
||||||
|
} |
||||||
|
else { |
||||||
|
_MESSAGE("Failed to register SKSE menuEventHandler!"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void steamInit(StaticFunctionTag* tag) { |
||||||
|
startSteam(); |
||||||
|
} |
||||||
|
|
||||||
|
void startSteam() |
||||||
|
{ |
||||||
|
try { |
||||||
|
if (singleton.get() == nullptr) { |
||||||
|
SteamAPI_Shutdown(); |
||||||
|
SetEnvironmentVariable("SteamAppID", "933480"); |
||||||
|
SetEnvironmentVariable("SteamGameId", "933480"); |
||||||
|
bool success = SteamAPI_Init(); |
||||||
|
if (success) |
||||||
|
_MESSAGE("Steam api init was successfull"); |
||||||
|
else |
||||||
|
_MESSAGE("Error while initializing the steam api"); |
||||||
|
|
||||||
|
singleton.swap(std::make_unique<AchievementHolder>()); |
||||||
|
singleton->start(); |
||||||
|
} |
||||||
|
else { |
||||||
|
_MESSAGE("Already initialized steam api, skipping it"); |
||||||
|
} |
||||||
|
} |
||||||
|
catch (const std::exception& ex) { |
||||||
|
std::string msg = "Exception while initializing the Steam API, steam achievements will not be available: " + std::string(ex.what()); |
||||||
|
_MESSAGE(msg.c_str()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
bool RegisterFuncs(VMClassRegistry * registry) |
||||||
|
{ |
||||||
|
registry->RegisterFunction(new NativeFunction1<StaticFunctionTag, bool, BSFixedString>("UnlockAchievement", "Game", Achievements::setAchievementUnlocked, registry)); |
||||||
|
registry->RegisterFunction( new NativeFunction0<StaticFunctionTag, void>("SteamInit", "Game", Achievements::steamInit, registry)); |
||||||
|
Achievements::registerMainMenuEvent(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
AchievementHolder::AchievementHolder() : stats(SteamUserStats()), callback(this, &AchievementHolder::onUserStatsReceived) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
void AchievementHolder::onUserStatsReceived(UserStatsReceived_t * event) { |
||||||
|
try { |
||||||
|
std::string msg = "User id: " + std::to_string(event->m_steamIDUser.ConvertToUint64()) + ", game id: " + std::to_string(event->m_nGameID) + ", success state: " + std::to_string(event->m_eResult); |
||||||
|
_MESSAGE(msg.c_str()); |
||||||
|
|
||||||
|
uint32 achievementCount = this->stats->GetNumAchievements(); |
||||||
|
msg = "There are " + std::to_string(achievementCount) + " achievements"; |
||||||
|
_MESSAGE(msg.c_str()); |
||||||
|
} |
||||||
|
catch (const std::exception& ex) { |
||||||
|
std::string msg = "Exception during steam callback: onUserStatsReceived. Failed to print data: " + std::string(ex.what()); |
||||||
|
_MESSAGE(msg.c_str()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool AchievementHolder::setAchievementUnlocked(const char * achievementName) |
||||||
|
{ |
||||||
|
std::string msg = "Unlocking achievement: " + std::string(achievementName); |
||||||
|
_MESSAGE(msg.c_str()); |
||||||
|
bool success = this->stats->SetAchievement(achievementName); |
||||||
|
if (!success) { |
||||||
|
_MESSAGE("Error while unlocking achievement"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
success = this->stats->StoreStats(); |
||||||
|
if (!success) { |
||||||
|
_MESSAGE("Error while storing unlocked achievement"); |
||||||
|
} |
||||||
|
return success; |
||||||
|
} |
||||||
|
|
||||||
|
void AchievementHolder::start() |
||||||
|
{ |
||||||
|
this->stats->RequestCurrentStats(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
#pragma once |
||||||
|
#include "skse64/PapyrusNativeFunctions.h" |
||||||
|
#include "skse64/GameReferences.h" |
||||||
|
//Steam API Version 1.31 matches the Skyrim Steam API version
|
||||||
|
#include "steam\steam_api.h" |
||||||
|
#include <memory> |
||||||
|
|
||||||
|
namespace Achievements { |
||||||
|
|
||||||
|
class AchievementHolder { |
||||||
|
private: |
||||||
|
ISteamUserStats * stats; |
||||||
|
CCallback<AchievementHolder, UserStatsReceived_t, false> callback; |
||||||
|
|
||||||
|
public: |
||||||
|
AchievementHolder(); |
||||||
|
|
||||||
|
void start(); |
||||||
|
void onUserStatsReceived(UserStatsReceived_t * event); |
||||||
|
bool setAchievementUnlocked(const char * achievementName); |
||||||
|
}; |
||||||
|
|
||||||
|
static std::unique_ptr<AchievementHolder> singleton(nullptr); |
||||||
|
|
||||||
|
void startSteam(); |
||||||
|
void registerMainMenuEvent(); |
||||||
|
|
||||||
|
bool setAchievementUnlocked(StaticFunctionTag* tag, BSFixedString achievement); |
||||||
|
void steamInit(StaticFunctionTag* tag); |
||||||
|
bool RegisterFuncs(VMClassRegistry* registry); |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
#include "CreatePotion.h" |
||||||
|
#include "skse64\GameObjects.h" |
||||||
|
#include "skse64\GameData.h" |
||||||
|
#include <string> |
||||||
|
|
||||||
|
namespace CreatePotion { |
||||||
|
|
||||||
|
AlchemyItem * createPotion(StaticFunctionTag * tag, VMArray<EffectSetting*> effects, VMArray<float> magnitudes, VMArray<UInt32> areas, VMArray<UInt32> durations, UInt32 arraySize) |
||||||
|
{ |
||||||
|
AlchemyItem * result = NULL; |
||||||
|
|
||||||
|
if (effects.Length() >= arraySize && magnitudes.Length() >= arraySize && areas.Length() >= arraySize && durations.Length() >= arraySize) { |
||||||
|
tArray<MagicItem::EffectItem> effectItems; |
||||||
|
effectItems.Allocate(arraySize); |
||||||
|
|
||||||
|
UInt32 count = 0; |
||||||
|
for (UInt32 i = 0; i < arraySize; ++i) { |
||||||
|
EffectSetting * magicEffect = NULL; |
||||||
|
effects.Get(&magicEffect, i); |
||||||
|
if (magicEffect) { // Only add effects that actually exist
|
||||||
|
magnitudes.Get(&effectItems[count].magnitude, i); |
||||||
|
areas.Get(&effectItems[count].area, i); |
||||||
|
durations.Get(&effectItems[count].duration, i); |
||||||
|
effectItems[count].mgef = magicEffect; |
||||||
|
++count; |
||||||
|
} |
||||||
|
} |
||||||
|
effectItems.count = count; // Set count to existing count
|
||||||
|
CALL_MEMBER_FN(PersistentFormManager::GetSingleton(), CreatePotion)(&result, &effectItems); |
||||||
|
Heap_Free(effectItems.entries); |
||||||
|
} |
||||||
|
else { |
||||||
|
_MESSAGE("Illegal arrays for creating a potion"); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
typedef AlchemyItem*(*CreatePotionType)(StaticFunctionTag * tag, VMArray<EffectSetting*> effects, VMArray<float> magnitudes, VMArray<UInt32> areas, VMArray<UInt32> durations); |
||||||
|
|
||||||
|
bool RegisterFuncs(VMClassRegistry* registry) { |
||||||
|
registry->RegisterFunction( |
||||||
|
new NativeFunction5<StaticFunctionTag, AlchemyItem *, VMArray<EffectSetting*>, VMArray<float>, VMArray<UInt32>, VMArray<UInt32>, UInt32>("CreatePotion", "EnderalLib", CreatePotion::createPotion, registry)); |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
#pragma once |
||||||
|
#include "skse64/PapyrusNativeFunctions.h" |
||||||
|
#include "skse64/GameReferences.h" |
||||||
|
#include "skse64/GameObjects.h" |
||||||
|
|
||||||
|
namespace CreatePotion |
||||||
|
{ |
||||||
|
AlchemyItem* createPotion(AlchemyItem* toCopy, VMArray<EffectSetting*> effects, VMArray<float> magnitudes, VMArray<UInt32> areas, VMArray<UInt32> durations, UInt32 arraySize); |
||||||
|
|
||||||
|
bool RegisterFuncs(VMClassRegistry* registry); |
||||||
|
} |
@ -0,0 +1,157 @@ |
|||||||
|
#include "PhasmalistInventoryFunctions.h" |
||||||
|
#include "skse64\GameExtraData.h" |
||||||
|
#include "skse64\GameBSExtraData.h" |
||||||
|
#include "skse64\GameRTTI.h" |
||||||
|
#include "skse64\PapyrusWornObject.h" |
||||||
|
#include "skse64\PapyrusEnchantment.h" |
||||||
|
#include "skse64\PapyrusWeapon.h" |
||||||
|
#include "skse64\PapyrusArmor.h" |
||||||
|
#include "skse64\PapyrusBook.h" |
||||||
|
#include "skse64\PapyrusSpell.h" |
||||||
|
#include <string> |
||||||
|
|
||||||
|
namespace PhasmalistScripts { |
||||||
|
|
||||||
|
static constexpr float magicWeight = 0.1; |
||||||
|
|
||||||
|
EntryDataList * getEntryData(TESObjectREFR *container) { |
||||||
|
ExtraContainerChanges * ecc = DYNAMIC_CAST |
||||||
|
(container->extraData.GetByType(kExtraData_ContainerChanges), BSExtraData, ExtraContainerChanges); |
||||||
|
if (!ecc) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
return ecc->data->objList; |
||||||
|
} |
||||||
|
|
||||||
|
float getMagicEffectStrength(EffectSetting * magicEffect, float magnitude, float area, float duration) { |
||||||
|
float result = magicEffect->properties.baseCost; |
||||||
|
if (magnitude > 0) { |
||||||
|
result *= magnitude; |
||||||
|
} |
||||||
|
if (area > 0) { |
||||||
|
result *= area; |
||||||
|
} |
||||||
|
if (duration > 0) { |
||||||
|
result *= duration; |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
float getEnchantmentStrength(EnchantmentItem * ench) { |
||||||
|
if (!ench) { |
||||||
|
return 0.0; |
||||||
|
} |
||||||
|
float result = 0; |
||||||
|
for (int i = papyrusEnchantment::GetNumEffects(ench) - 1; i >= 0; i--) { |
||||||
|
result += getMagicEffectStrength( |
||||||
|
papyrusEnchantment::GetNthEffectMagicEffect(ench, i), |
||||||
|
papyrusEnchantment::GetNthEffectMagnitude(ench, i), |
||||||
|
papyrusEnchantment::GetNthEffectArea(ench, i), |
||||||
|
papyrusEnchantment::GetNthEffectDuration(ench, i)); |
||||||
|
} |
||||||
|
return result * magicWeight; |
||||||
|
} |
||||||
|
|
||||||
|
float getSpellStrength(SpellItem * spell) { |
||||||
|
if (!spell) { |
||||||
|
return 0.0; |
||||||
|
} |
||||||
|
float result = 0; |
||||||
|
for (int i = papyrusSpell::GetNumEffects(spell) - 1; i >= 0; i--) { |
||||||
|
result += getMagicEffectStrength( |
||||||
|
papyrusSpell::GetNthEffectMagicEffect(spell, i), |
||||||
|
papyrusSpell::GetNthEffectMagnitude(spell, i), |
||||||
|
papyrusSpell::GetNthEffectDuration(spell, i), |
||||||
|
papyrusSpell::GetNthEffectArea(spell, i)); |
||||||
|
} |
||||||
|
return result * magicWeight; |
||||||
|
} |
||||||
|
|
||||||
|
float getAdditionalExtendDataStrength(InventoryEntryData * itemStack, float physicalStrength) { |
||||||
|
float strength = 0; |
||||||
|
for (int i = itemStack->extendDataList->Count() - 1; i >= 0; i--) { |
||||||
|
BaseExtraList * extraData = itemStack->extendDataList->GetNthItem(i); |
||||||
|
if (!extraData) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
ExtraCount * exCount = DYNAMIC_CAST(extraData->GetByType(kExtraData_Count), BSExtraData, ExtraCount); |
||||||
|
int count = 1; |
||||||
|
if (exCount) { |
||||||
|
count = exCount->count; |
||||||
|
} |
||||||
|
if (extraData->HasType(kExtraData_Enchantment)) { |
||||||
|
//item has been enchanted
|
||||||
|
EnchantmentItem * ench = referenceUtils::GetEnchantment(extraData); |
||||||
|
strength += getEnchantmentStrength(ench) * count; |
||||||
|
} |
||||||
|
if (extraData->HasType(kExtraData_Health)) { |
||||||
|
//item has been tempered
|
||||||
|
ExtraHealth * health = DYNAMIC_CAST(extraData->GetByType(kExtraData_Health), BSExtraData, ExtraHealth); |
||||||
|
if (health) { |
||||||
|
strength += physicalStrength * (health->health - 1.0) * count; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return strength; |
||||||
|
} |
||||||
|
|
||||||
|
float getItemStackStrength(InventoryEntryData * itemStack) { |
||||||
|
float strength = 0; |
||||||
|
float physicalStrength = 0; |
||||||
|
|
||||||
|
if (itemStack->type->IsWeapon()) { |
||||||
|
TESObjectWEAP * asWeapon = static_cast<TESObjectWEAP*>(itemStack->type); |
||||||
|
if (asWeapon) { |
||||||
|
float baseDmg = papyrusWeapon::GetBaseDamage(asWeapon); |
||||||
|
float speed = papyrusWeapon::GetSpeed(asWeapon); |
||||||
|
physicalStrength = baseDmg * speed; |
||||||
|
strength += physicalStrength; |
||||||
|
strength += getEnchantmentStrength(papyrusWeapon::GetEnchantment(asWeapon)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (itemStack->type->IsArmor()) { |
||||||
|
TESObjectARMO * asArmor = static_cast<TESObjectARMO*>(itemStack->type); |
||||||
|
if (asArmor) { |
||||||
|
physicalStrength = papyrusArmor::GetArmorRating(asArmor); |
||||||
|
strength += physicalStrength; |
||||||
|
strength += getEnchantmentStrength(papyrusArmor::GetEnchantment(asArmor)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (itemStack->type->formType == kFormType_Book) { |
||||||
|
TESObjectBOOK * asBook = static_cast<TESObjectBOOK*>(itemStack->type); |
||||||
|
if (asBook) { |
||||||
|
SpellItem * spell = papyrusBook::GetSpell(asBook); |
||||||
|
return getSpellStrength(spell); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
strength = strength * itemStack->countDelta; |
||||||
|
|
||||||
|
strength += getAdditionalExtendDataStrength(itemStack, physicalStrength); |
||||||
|
|
||||||
|
return strength; |
||||||
|
} |
||||||
|
|
||||||
|
float calculateContentStrength(StaticFunctionTag * tag, TESObjectREFR *container) { |
||||||
|
if (!container) { |
||||||
|
return 0.0; |
||||||
|
} |
||||||
|
float strength = 0; |
||||||
|
for (int i = getEntryData(container)->Count() - 1; i >= 0; --i) { |
||||||
|
InventoryEntryData * ed = getEntryData(container)->GetNthItem(i); |
||||||
|
if (!ed) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
strength += getItemStackStrength(ed); |
||||||
|
} |
||||||
|
return strength; |
||||||
|
} |
||||||
|
|
||||||
|
bool RegisterFuncs(VMClassRegistry* registry) { |
||||||
|
registry->RegisterFunction( |
||||||
|
new NativeFunction1<StaticFunctionTag, float, TESObjectREFR *>("calculateContentStrength", "EnderalLib", PhasmalistScripts::calculateContentStrength, registry)); |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
#pragma once |
||||||
|
#include "skse64/PapyrusNativeFunctions.h" |
||||||
|
#include "skse64/GameReferences.h" |
||||||
|
|
||||||
|
namespace PhasmalistScripts |
||||||
|
{ |
||||||
|
float calculateContentStrength(TESObjectREFR *base); |
||||||
|
|
||||||
|
bool RegisterFuncs(VMClassRegistry* registry); |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
LIBRARY "fs" |
||||||
|
EXPORTS |
||||||
|
SKSEPlugin_Query |
||||||
|
SKSEPlugin_Load |
@ -0,0 +1,69 @@ |
|||||||
|
#include "skse64/PluginAPI.h" // super |
||||||
|
#include "skse64_common/skse_version.h" // What version of SKSE is running? |
||||||
|
#include <shlobj.h> // CSIDL_MYCODUMENTS |
||||||
|
|
||||||
|
#include "PhasmalistInventoryFunctions.h" |
||||||
|
#include "CreatePotion.h" |
||||||
|
|
||||||
|
static PluginHandle g_pluginHandle = kPluginHandle_Invalid; |
||||||
|
static SKSEPapyrusInterface * g_papyrus = NULL; |
||||||
|
|
||||||
|
extern "C" { |
||||||
|
|
||||||
|
bool SKSEPlugin_Query(const SKSEInterface * skse, PluginInfo * info) { // Called by SKSE to learn about this plugin and check that it's safe to load it
|
||||||
|
gLog.OpenRelative(CSIDL_MYDOCUMENTS, "\\My Games\\Enderal Special Edition\\SKSE\\FS.log"); |
||||||
|
gLog.SetPrintLevel(IDebugLog::kLevel_Error); |
||||||
|
gLog.SetLogLevel(IDebugLog::kLevel_DebugMessage); |
||||||
|
|
||||||
|
_MESSAGE("fs_skse_functions"); |
||||||
|
|
||||||
|
// populate info structure
|
||||||
|
info->infoVersion = PluginInfo::kInfoVersion; |
||||||
|
info->name = "fs_skse_functions"; |
||||||
|
info->version = 1; |
||||||
|
|
||||||
|
// store plugin handle so we can identify ourselves later
|
||||||
|
g_pluginHandle = skse->GetPluginHandle(); |
||||||
|
|
||||||
|
if (skse->isEditor) |
||||||
|
{ |
||||||
|
_MESSAGE("loaded in editor, marking as incompatible"); |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
else if (skse->runtimeVersion != RUNTIME_VERSION_1_5_97) |
||||||
|
{ |
||||||
|
_MESSAGE("unsupported runtime version %08X", skse->runtimeVersion); |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
// ### do not do anything else in this callback
|
||||||
|
// ### only fill out PluginInfo and return true/false
|
||||||
|
|
||||||
|
// supported runtime version
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool SKSEPlugin_Load(const SKSEInterface * skse) { // Called by SKSE to load this plugin
|
||||||
|
_MESSAGE("fs_skse_functions loaded"); |
||||||
|
|
||||||
|
g_papyrus = (SKSEPapyrusInterface *)skse->QueryInterface(kInterface_Papyrus); |
||||||
|
|
||||||
|
//Check if the function registration was a success...
|
||||||
|
bool btest = g_papyrus->Register(PhasmalistScripts::RegisterFuncs); |
||||||
|
|
||||||
|
if (btest) { |
||||||
|
_MESSAGE("Register Succeeded: Phasmalist functions"); |
||||||
|
} |
||||||
|
|
||||||
|
btest = g_papyrus->Register(CreatePotion::RegisterFuncs); |
||||||
|
|
||||||
|
if (btest) { |
||||||
|
_MESSAGE("Register Succeeded: CreatePotion functions"); |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
}; |
@ -0,0 +1,4 @@ |
|||||||
|
#include "skse64/BSModelDB.h" |
||||||
|
|
||||||
|
// 206875324DD3C045FB854CB2889AFBCA94C7790B+89
|
||||||
|
RelocPtr <BSModelDB::BSModelProcessor*> g_TESProcessor(0x01EC3C10); |
@ -0,0 +1,50 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "skse64_common/Utilities.h" |
||||||
|
|
||||||
|
class NiAVObject; |
||||||
|
|
||||||
|
class BSModelDB |
||||||
|
{ |
||||||
|
public: |
||||||
|
struct ModelData |
||||||
|
{ |
||||||
|
UInt64 unk00; // 00
|
||||||
|
|
||||||
|
enum |
||||||
|
{ |
||||||
|
kFlag_Unk1 = (1 << 0), |
||||||
|
kFlag_Dynamic = (1 << 1), |
||||||
|
kFlag_PostProcess = (1 << 3), |
||||||
|
kFlag_Unk2 = (1 << 4), |
||||||
|
kFlag_Unk3 = (1 << 5) |
||||||
|
}; |
||||||
|
|
||||||
|
UInt8 modelFlags; // 08
|
||||||
|
// ...
|
||||||
|
}; |
||||||
|
|
||||||
|
class BSModelProcessor |
||||||
|
{ |
||||||
|
public: |
||||||
|
virtual ~BSModelProcessor() { }; |
||||||
|
|
||||||
|
virtual void Process(ModelData * modelData, const char * modelName, NiAVObject ** root, UInt32 * typeOut) { }; |
||||||
|
}; |
||||||
|
|
||||||
|
class TESProcessor : public BSModelProcessor |
||||||
|
{ |
||||||
|
public: |
||||||
|
TESProcessor() { } |
||||||
|
virtual ~TESProcessor() { CALL_MEMBER_FN(this, dtor)(); }; |
||||||
|
|
||||||
|
virtual void Process(ModelData * modelData, const char * modelName, NiAVObject ** root, UInt32 * typeOut) override { CALL_MEMBER_FN(this, Impl_Process)(modelData, modelName, root, typeOut); } |
||||||
|
|
||||||
|
MEMBER_FN_PREFIX(TESProcessor); |
||||||
|
// find from ??_7BSModelProcessor@BSModelDB@@6B@
|
||||||
|
DEFINE_MEMBER_FN(dtor, void, 0x00D2ECA0); |
||||||
|
DEFINE_MEMBER_FN(Impl_Process, void, 0x00181800, ModelData * modelData, const char * modelName, NiAVObject ** root, UInt32 * typeOut); |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
extern RelocPtr <BSModelDB::BSModelProcessor*> g_TESProcessor; |
@ -0,0 +1,198 @@ |
|||||||
|
#include "Colors.h" |
||||||
|
|
||||||
|
UInt32 ARGBColor::GetColor() |
||||||
|
{ |
||||||
|
return MAKE_COLOR(m_alpha, m_red, m_green, m_blue); |
||||||
|
} |
||||||
|
|
||||||
|
void ARGBColor::SetARGB(UInt8 alpha, UInt8 red, UInt8 green, UInt8 blue) |
||||||
|
{ |
||||||
|
m_alpha = alpha; |
||||||
|
m_red = red; |
||||||
|
m_green = green; |
||||||
|
m_blue = blue; |
||||||
|
} |
||||||
|
|
||||||
|
void ARGBColor::GetARGB(UInt8 & alpha, UInt8 & red, UInt8 & green, UInt8 & blue) |
||||||
|
{ |
||||||
|
alpha = m_alpha; |
||||||
|
red = m_red; |
||||||
|
green = m_green; |
||||||
|
blue = m_blue; |
||||||
|
} |
||||||
|
|
||||||
|
void ARGBColor::SetHSV(double hue, double saturation, double value) |
||||||
|
{ |
||||||
|
double h,s,v; |
||||||
|
double r,g,b; |
||||||
|
|
||||||
|
h = hue; |
||||||
|
s = saturation; |
||||||
|
v = value; |
||||||
|
|
||||||
|
if (hue < 0.0) |
||||||
|
hue += 360.0; |
||||||
|
|
||||||
|
if (s != 0.0) { |
||||||
|
double f, p, q, t; |
||||||
|
if (h == 360.0) |
||||||
|
h = 0.0; |
||||||
|
h /= 60.0; |
||||||
|
|
||||||
|
int i = (int)h; |
||||||
|
f = h - i; |
||||||
|
p = v * (1.0 - s); |
||||||
|
q = v * (1.0 - (s * f)); |
||||||
|
t = v * (1.0 - (s * (1.0 - f))); |
||||||
|
|
||||||
|
switch (i) { |
||||||
|
case 0: r = v; g = t; b = p; break; |
||||||
|
case 1: r = q; g = v; b = p; break; |
||||||
|
case 2: r = p; g = v; b = t; break; |
||||||
|
case 3: r = p; g = q; b = v; break; |
||||||
|
case 4: r = t; g = p; b = v; break; |
||||||
|
case 5: r = v; g = p; b = q; break; |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
r = v; |
||||||
|
g = v; |
||||||
|
b = v; |
||||||
|
} |
||||||
|
|
||||||
|
m_red = r * 255; |
||||||
|
m_green = g * 255; |
||||||
|
m_blue = b * 255; |
||||||
|
} |
||||||
|
|
||||||
|
void ARGBColor::GetHSV(double & hue, double & saturation, double & value) |
||||||
|
{ |
||||||
|
double r,g,b, rgb_max, rgb_min, delta, h, s; |
||||||
|
r = m_red / 255.0; |
||||||
|
g = m_green / 255.0; |
||||||
|
b = m_blue / 255.0; |
||||||
|
rgb_max = MAX3(r, g, b); |
||||||
|
rgb_min = MIN3(r, g, b); |
||||||
|
delta = rgb_max - rgb_min; |
||||||
|
h = 0; |
||||||
|
s = 0; |
||||||
|
|
||||||
|
if ( rgb_max != 0.0 ) |
||||||
|
s = delta / rgb_max; |
||||||
|
|
||||||
|
if ( s != 0.0 ) |
||||||
|
{ |
||||||
|
double rc = (rgb_max - r) / delta; |
||||||
|
double gc = (rgb_max - g) / delta; |
||||||
|
double bc = (rgb_max - b) / delta; |
||||||
|
|
||||||
|
if ( r == rgb_max ) |
||||||
|
h = bc - gc; |
||||||
|
else if ( g == rgb_max ) |
||||||
|
h = 2.0f + rc - bc; |
||||||
|
else if ( b == rgb_max ) |
||||||
|
h = 4.0f + gc - rc; |
||||||
|
|
||||||
|
h *= 60.0f; |
||||||
|
if ( h < 0.0 ) |
||||||
|
h += 360.0f; |
||||||
|
} |
||||||
|
|
||||||
|
hue = h; |
||||||
|
saturation = s; |
||||||
|
value = rgb_max; |
||||||
|
} |
||||||
|
|
||||||
|
UInt8 ARGBColor::GetAlpha() |
||||||
|
{ |
||||||
|
return m_alpha; |
||||||
|
} |
||||||
|
|
||||||
|
UInt8 ARGBColor::GetRed() |
||||||
|
{ |
||||||
|
return m_red; |
||||||
|
} |
||||||
|
|
||||||
|
UInt8 ARGBColor::GetGreen() |
||||||
|
{ |
||||||
|
return m_green; |
||||||
|
} |
||||||
|
|
||||||
|
UInt8 ARGBColor::GetBlue() |
||||||
|
{ |
||||||
|
return m_blue; |
||||||
|
} |
||||||
|
|
||||||
|
void ARGBColor::SetAlpha(UInt8 alpha) |
||||||
|
{ |
||||||
|
m_alpha = alpha; |
||||||
|
} |
||||||
|
|
||||||
|
void ARGBColor::SetRed(UInt8 red) |
||||||
|
{ |
||||||
|
m_red = red; |
||||||
|
} |
||||||
|
|
||||||
|
void ARGBColor::SetGreen(UInt8 green) |
||||||
|
{ |
||||||
|
m_green = green; |
||||||
|
} |
||||||
|
|
||||||
|
void ARGBColor::SetBlue(UInt8 blue) |
||||||
|
{ |
||||||
|
m_blue = blue; |
||||||
|
} |
||||||
|
|
||||||
|
void ARGBColor::SetHue(double newHue) |
||||||
|
{ |
||||||
|
double hue; |
||||||
|
double sat; |
||||||
|
double val; |
||||||
|
GetHSV(hue, sat, val); |
||||||
|
SetHSV(newHue, sat, val); |
||||||
|
} |
||||||
|
|
||||||
|
void ARGBColor::SetSaturation(double newSat) |
||||||
|
{ |
||||||
|
double hue; |
||||||
|
double sat; |
||||||
|
double val; |
||||||
|
GetHSV(hue, sat, val); |
||||||
|
SetHSV(hue, newSat, val); |
||||||
|
} |
||||||
|
|
||||||
|
void ARGBColor::SetValue(double newVal) |
||||||
|
{ |
||||||
|
double hue; |
||||||
|
double sat; |
||||||
|
double val; |
||||||
|
GetHSV(hue, sat, val); |
||||||
|
SetHSV(hue, sat, newVal); |
||||||
|
} |
||||||
|
|
||||||
|
double ARGBColor::GetHue() |
||||||
|
{ |
||||||
|
double hue; |
||||||
|
double sat; |
||||||
|
double val; |
||||||
|
GetHSV(hue, sat, val); |
||||||
|
return hue; |
||||||
|
} |
||||||
|
|
||||||
|
double ARGBColor::GetSaturation() |
||||||
|
{ |
||||||
|
double hue; |
||||||
|
double sat; |
||||||
|
double val; |
||||||
|
GetHSV(hue, sat, val); |
||||||
|
return sat; |
||||||
|
} |
||||||
|
|
||||||
|
double ARGBColor::GetValue() |
||||||
|
{ |
||||||
|
double hue; |
||||||
|
double sat; |
||||||
|
double val; |
||||||
|
GetHSV(hue, sat, val); |
||||||
|
return val; |
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "common/ITypes.h" |
||||||
|
|
||||||
|
#define MIN3(x,y,z) ((y) <= (z) ? ((x) <= (y) ? (x) : (y)) : ((x) <= (z) ? (x) : (z))) |
||||||
|
#define MAX3(x,y,z) ((y) >= (z) ? ((x) >= (y) ? (x) : (y)) : ((x) >= (z) ? (x) : (z))) |
||||||
|
|
||||||
|
class ARGBColor |
||||||
|
{ |
||||||
|
public: |
||||||
|
ARGBColor(UInt32 argb) { |
||||||
|
m_alpha = COLOR_ALPHA(argb); |
||||||
|
m_red = COLOR_RED(argb); |
||||||
|
m_green = COLOR_GREEN(argb); |
||||||
|
m_blue = COLOR_BLUE(argb); |
||||||
|
}; |
||||||
|
ARGBColor(UInt8 _a, UInt8 _r, UInt8 _g, UInt8 _b) : m_alpha(_a), m_red(_r), m_green(_g), m_blue(_b) {}; |
||||||
|
|
||||||
|
UInt32 GetColor(); |
||||||
|
|
||||||
|
void SetARGB(UInt8 alpha, UInt8 red, UInt8 green, UInt8 blue); |
||||||
|
void GetARGB(UInt8 & alpha, UInt8 & red, UInt8 & green, UInt8 & blue); |
||||||
|
|
||||||
|
void SetHSV(double hue, double saturation, double value); |
||||||
|
void GetHSV(double & hue, double & saturation, double & value); |
||||||
|
|
||||||
|
UInt8 GetAlpha(); |
||||||
|
UInt8 GetRed(); |
||||||
|
UInt8 GetGreen(); |
||||||
|
UInt8 GetBlue(); |
||||||
|
|
||||||
|
void SetAlpha(UInt8 alpha); |
||||||
|
void SetRed(UInt8 red); |
||||||
|
void SetGreen(UInt8 green); |
||||||
|
void SetBlue(UInt8 blue); |
||||||
|
|
||||||
|
void SetHue(double hue); |
||||||
|
void SetSaturation(double saturation); |
||||||
|
void SetValue(double value); |
||||||
|
|
||||||
|
double GetHue(); |
||||||
|
double GetSaturation(); |
||||||
|
double GetValue(); |
||||||
|
|
||||||
|
private: |
||||||
|
UInt8 m_alpha; |
||||||
|
UInt8 m_red; |
||||||
|
UInt8 m_green; |
||||||
|
UInt8 m_blue; |
||||||
|
}; |
@ -0,0 +1,17 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||||
|
<ImportGroup Label="PropertySheets" /> |
||||||
|
<PropertyGroup Label="UserMacros" /> |
||||||
|
<PropertyGroup> |
||||||
|
<TargetName>$(ProjectName)_1_5_97</TargetName> |
||||||
|
</PropertyGroup> |
||||||
|
<ItemDefinitionGroup> |
||||||
|
<ClCompile> |
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
||||||
|
<ForcedIncludeFiles>common/IPrefix.h</ForcedIncludeFiles> |
||||||
|
<WarningLevel>Level3</WarningLevel> |
||||||
|
<PreprocessorDefinitions>_WINDOWS;_USRDLL;SKSE64_EXPORTS;RUNTIME_VERSION=0x01050610;RUNTIME;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||||
|
</ClCompile> |
||||||
|
</ItemDefinitionGroup> |
||||||
|
<ItemGroup /> |
||||||
|
</Project> |
@ -0,0 +1,75 @@ |
|||||||
|
#include "skse64/CustomMenu.h" |
||||||
|
|
||||||
|
std::string CustomMenuCreator::swfPath_; |
||||||
|
|
||||||
|
IMenu* CustomMenuCreator::Create(void) |
||||||
|
{ |
||||||
|
void* p = ScaleformHeap_Allocate(sizeof(CustomMenu)); |
||||||
|
if (p) |
||||||
|
{ |
||||||
|
IMenu* menu = new (p) CustomMenu(swfPath_.c_str()); |
||||||
|
return menu; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void CustomMenuCreator::SetSwfPath(const char* path) |
||||||
|
{ |
||||||
|
swfPath_ = path; |
||||||
|
} |
||||||
|
|
||||||
|
CustomMenu::CustomMenu(const char* swfPath) |
||||||
|
{ |
||||||
|
CALL_MEMBER_FN(GFxLoader::GetSingleton(), LoadMovie)(this, &view, swfPath, GFxMovieView::ScaleModeType::kNoBorder, 0.0); |
||||||
|
|
||||||
|
flags = IMenu::kFlag_Modal | IMenu::kFlag_PausesGame; |
||||||
|
unk0C = 0xA; |
||||||
|
unk14 = 1; |
||||||
|
|
||||||
|
if(!InputEventDispatcher::GetSingleton()->IsGamepadEnabled()) |
||||||
|
flags |= IMenu::kFlag_UpdateUsesCursor | IMenu::kFlag_UsesCursor; // Shows the cursor when no gamepad is enabled
|
||||||
|
|
||||||
|
#ifdef _CUSTOMMENU_ITEMDISPLAY |
||||||
|
flags |= IMenu::kFlag_RendersOffscreenTargets; |
||||||
|
#endif |
||||||
|
} |
||||||
|
#ifdef _CUSTOMMENU_ITEMDISPLAY |
||||||
|
void UpdateItem3D(const FxDelegateArgs & params) |
||||||
|
{ |
||||||
|
if(params.menu) { |
||||||
|
UInt32 formId = (UInt32)params.args->GetNumber(); |
||||||
|
if(formId) { |
||||||
|
TESForm * form = LookupFormByID(formId); |
||||||
|
if(form) { |
||||||
|
CALL_MEMBER_FN(Inventory3DManager::GetSingleton(), UpdateMagic3D)(form, 0); |
||||||
|
} |
||||||
|
} else { |
||||||
|
CALL_MEMBER_FN(Inventory3DManager::GetSingleton(), Clear3D)(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
#endif |
||||||
|
void CustomMenu::Accept(CallbackProcessor * processor) |
||||||
|
{ |
||||||
|
GString playSound("PlaySound"); |
||||||
|
processor->Process(playSound, PlaySoundCallback); |
||||||
|
|
||||||
|
#ifdef _CUSTOMMENU_ITEMDISPLAY |
||||||
|
GString renderItem("UpdateItem3D"); |
||||||
|
processor->Process(renderItem, UpdateItem3D); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void CustomMenu::Render() |
||||||
|
{ |
||||||
|
if(view) { |
||||||
|
view->Render(); |
||||||
|
#ifdef _CUSTOMMENU_ITEMDISPLAY |
||||||
|
CALL_MEMBER_FN(Inventory3DManager::GetSingleton(), Render)(); |
||||||
|
#endif |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "skse64/GameMenus.h" |
||||||
|
#include "skse64/ScaleformLoader.h" |
||||||
|
|
||||||
|
class CustomMenuCreator |
||||||
|
{ |
||||||
|
public: |
||||||
|
static IMenu* Create(void); |
||||||
|
static void SetSwfPath(const char* path); |
||||||
|
|
||||||
|
private: |
||||||
|
CustomMenuCreator(); |
||||||
|
|
||||||
|
static std::string swfPath_; |
||||||
|
}; |
||||||
|
|
||||||
|
class CustomMenu : public IMenu |
||||||
|
{ |
||||||
|
public: |
||||||
|
CustomMenu(const char* swfPath); |
||||||
|
virtual void Accept(CallbackProcessor * processor); |
||||||
|
virtual void Render(void); |
||||||
|
}; |
@ -0,0 +1,70 @@ |
|||||||
|
#include "skse64/GameAPI.h" |
||||||
|
|
||||||
|
// 4371A3D33EB5D62C7C548EBD5F760AF15A9B0B96+41
|
||||||
|
RelocPtr <Heap> g_mainHeap(0x01EBD280); |
||||||
|
|
||||||
|
// 75643FD50A96D1F83B1AC4797EC84EF1C53039AC+68
|
||||||
|
RelocPtr <ConsoleManager *> g_console(0x02F000F0); |
||||||
|
|
||||||
|
// E1E59B64FDA5B8A9085AE9314353ABEEA0DB2823+C4
|
||||||
|
RelocPtr <UInt32> g_consoleHandle(0x02F4C31C); |
||||||
|
|
||||||
|
// 52DD97B7C619EA732D3CD95637F449FC7A23DD12+24
|
||||||
|
RelocPtr<UInt32> g_TlsIndexPtr(0x03497408); |
||||||
|
|
||||||
|
// BC8BF08A45C960EB35F2BAFEC9432C80365A1473+14A
|
||||||
|
RelocPtr<PlayerCharacter*> g_thePlayer(0x02F26EF8); |
||||||
|
|
||||||
|
void * Heap_Allocate(size_t size) |
||||||
|
{ |
||||||
|
return CALL_MEMBER_FN(g_mainHeap, Allocate)(size, 0, false); |
||||||
|
} |
||||||
|
|
||||||
|
void Heap_Free(void * ptr) |
||||||
|
{ |
||||||
|
CALL_MEMBER_FN(g_mainHeap, Free)(ptr, false); |
||||||
|
} |
||||||
|
|
||||||
|
void Console_Print(const char * fmt, ...) |
||||||
|
{ |
||||||
|
ConsoleManager * mgr = *g_console; |
||||||
|
if(mgr) |
||||||
|
{ |
||||||
|
va_list args; |
||||||
|
va_start(args, fmt); |
||||||
|
|
||||||
|
CALL_MEMBER_FN(mgr, VPrint)(fmt, args); |
||||||
|
|
||||||
|
va_end(args); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
struct TLSData |
||||||
|
{ |
||||||
|
// thread local storage
|
||||||
|
|
||||||
|
UInt8 unk000[0x600]; // 000
|
||||||
|
UInt8 consoleMode; // 600
|
||||||
|
UInt8 pad601[7]; // 601
|
||||||
|
}; |
||||||
|
|
||||||
|
static TLSData * GetTLSData() |
||||||
|
{ |
||||||
|
UInt32 TlsIndex = *g_TlsIndexPtr; |
||||||
|
TLSData ** data = (TLSData **)__readgsqword(0x58); |
||||||
|
|
||||||
|
return data[TlsIndex]; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
bool IsConsoleMode(void) |
||||||
|
{ |
||||||
|
return GetTLSData()->consoleMode != 0; |
||||||
|
} |
||||||
|
|
||||||
|
__int64 GetPerfCounter(void) |
||||||
|
{ |
||||||
|
LARGE_INTEGER li; |
||||||
|
QueryPerformanceCounter(&li); |
||||||
|
return li.QuadPart; |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "skse64_common/Utilities.h" |
||||||
|
|
||||||
|
class PlayerCharacter; |
||||||
|
|
||||||
|
class Heap |
||||||
|
{ |
||||||
|
public: |
||||||
|
MEMBER_FN_PREFIX(Heap); |
||||||
|
DEFINE_MEMBER_FN(Allocate, void *, 0x00C02260, size_t size, size_t alignment, bool aligned); |
||||||
|
DEFINE_MEMBER_FN(Free, void, 0x00C02560, void * buf, bool aligned); |
||||||
|
}; |
||||||
|
|
||||||
|
extern RelocPtr <Heap> g_mainHeap; |
||||||
|
|
||||||
|
void * Heap_Allocate(size_t size); |
||||||
|
void Heap_Free(void * ptr); |
||||||
|
|
||||||
|
class ConsoleManager |
||||||
|
{ |
||||||
|
public: |
||||||
|
MEMBER_FN_PREFIX(ConsoleManager); |
||||||
|
DEFINE_MEMBER_FN(VPrint, void, 0x0085C2C0, const char * fmt, va_list args); |
||||||
|
// DEFINE_MEMBER_FN(Print, void, 0x001D2050, const char * str);
|
||||||
|
}; |
||||||
|
|
||||||
|
extern RelocPtr <ConsoleManager *> g_console; |
||||||
|
extern RelocPtr <UInt32> g_consoleHandle; |
||||||
|
extern RelocPtr <PlayerCharacter*> g_thePlayer; |
||||||
|
|
||||||
|
void Console_Print(const char * fmt, ...); |
||||||
|
bool IsConsoleMode(void); |
||||||
|
__int64 GetPerfCounter(void); |
@ -0,0 +1,280 @@ |
|||||||
|
#include "GameBSExtraData.h" |
||||||
|
#include "GameExtraData.h" |
||||||
|
#include "GameRTTI.h" |
||||||
|
|
||||||
|
extern const void * RTTIForExtraType[0xB4] =
|
||||||
|
{ |
||||||
|
NULL, // 0x0
|
||||||
|
RTTI_ExtraHavok, // 0x1,
|
||||||
|
RTTI_ExtraCell3D, // 0x2,
|
||||||
|
RTTI_ExtraCellWaterType, // 0x3,
|
||||||
|
RTTI_ExtraRegionList, // 0x4,
|
||||||
|
RTTI_ExtraSeenData, // 0x5,
|
||||||
|
RTTI_ExtraEditorID, // 0x6,
|
||||||
|
RTTI_ExtraCellMusicType, // 0x7,
|
||||||
|
RTTI_ExtraCellSkyRegion, // 0x8,
|
||||||
|
RTTI_ExtraProcessMiddleLow, // 0x9,
|
||||||
|
RTTI_ExtraDetachTime, // 0xA,
|
||||||
|
RTTI_ExtraPersistentCell, // 0xB,
|
||||||
|
NULL, // 0xC,
|
||||||
|
RTTI_ExtraAction, // 0xD,
|
||||||
|
RTTI_ExtraStartingPosition, // 0xE,
|
||||||
|
NULL, // 0xF,
|
||||||
|
RTTI_ExtraAnimGraphManager, // 0x10,
|
||||||
|
NULL, // 0x11,
|
||||||
|
RTTI_ExtraUsedMarkers, // 0x12,
|
||||||
|
RTTI_ExtraDistantData, // 0x13,
|
||||||
|
RTTI_ExtraRagDollData, // 0x14,
|
||||||
|
RTTI_ExtraContainerChanges, // 0x15,
|
||||||
|
RTTI_ExtraWorn, // 0x16,
|
||||||
|
RTTI_ExtraWornLeft, // 0x17,
|
||||||
|
RTTI_ExtraPackageStartLocation, // 0x18,
|
||||||
|
RTTI_ExtraPackage, // 0x19,
|
||||||
|
RTTI_ExtraTresPassPackage, // 0x1A,
|
||||||
|
RTTI_ExtraRunOncePacks, // 0x1B,
|
||||||
|
RTTI_ExtraReferenceHandle, // 0x1C,
|
||||||
|
RTTI_ExtraFollower, // 0x1D,
|
||||||
|
RTTI_ExtraLevCreaModifier, // 0x1E,
|
||||||
|
RTTI_ExtraGhost, // 0x1F,
|
||||||
|
RTTI_ExtraOriginalReference, // 0x20,
|
||||||
|
RTTI_ExtraOwnership, // 0x21,
|
||||||
|
RTTI_ExtraGlobal, // 0x22,
|
||||||
|
RTTI_ExtraRank, // 0x23,
|
||||||
|
RTTI_ExtraCount, // 0x24,
|
||||||
|
RTTI_ExtraHealth, // 0x25,
|
||||||
|
NULL, // 0x26,
|
||||||
|
RTTI_ExtraTimeLeft, // 0x27,
|
||||||
|
RTTI_ExtraCharge, // 0x28,
|
||||||
|
RTTI_ExtraLight, // 0x29,
|
||||||
|
RTTI_ExtraLock, // 0x2A,
|
||||||
|
RTTI_ExtraTeleport, // 0x2B,
|
||||||
|
RTTI_ExtraMapMarker, // 0x2C,
|
||||||
|
RTTI_ExtraLeveledCreature, // 0x2D,
|
||||||
|
RTTI_ExtraLeveledItem, // 0x2E,
|
||||||
|
RTTI_ExtraScale, // 0x2F,
|
||||||
|
NULL, // 0x30, was ExtraSeed, removed in 1.7.7.0
|
||||||
|
NULL, // 0x31,
|
||||||
|
NULL, // 0x32,
|
||||||
|
NULL, // 0x33,
|
||||||
|
RTTI_ExtraPlayerCrimeList, // 0x34,
|
||||||
|
NULL, // 0x35
|
||||||
|
RTTI_ExtraEnableStateParent, // 0x36,
|
||||||
|
RTTI_ExtraEnableStateChildren, // 0x37,
|
||||||
|
RTTI_ExtraItemDropper, // 0x38,
|
||||||
|
RTTI_ExtraDroppedItemList, // 0x39,
|
||||||
|
RTTI_ExtraRandomTeleportMarker, // 0x3A,
|
||||||
|
NULL, // 0x3B
|
||||||
|
RTTI_ExtraSavedHavokData, // 0x3C,
|
||||||
|
RTTI_ExtraCannotWear, // 0x3D,
|
||||||
|
RTTI_ExtraPoison, // 0x3E,
|
||||||
|
NULL, // 0x3F
|
||||||
|
RTTI_ExtraLastFinishedSequence, // 0x40,
|
||||||
|
RTTI_ExtraSavedAnimation, // 0x41,
|
||||||
|
RTTI_ExtraNorthRotation, // 0x42,
|
||||||
|
RTTI_ExtraSpawnContainer, // 0x43,
|
||||||
|
RTTI_ExtraFriendHits, // 0x44,
|
||||||
|
RTTI_ExtraHeadingTarget, // 0x45,
|
||||||
|
NULL, // 0x46
|
||||||
|
RTTI_ExtraRefractionProperty, // 0x47,
|
||||||
|
RTTI_ExtraStartingWorldOrCell, // 0x48,
|
||||||
|
RTTI_ExtraHotkey, // 0x49,
|
||||||
|
NULL, // 0x4A
|
||||||
|
RTTI_ExtraEditorRefMoveData, // 0x4B,
|
||||||
|
RTTI_ExtraInfoGeneralTopic, // 0x4C,
|
||||||
|
RTTI_ExtraHasNoRumors, // 0x4D,
|
||||||
|
RTTI_ExtraSound, // 0x4E,
|
||||||
|
RTTI_ExtraTerminalState, // 0x4F,
|
||||||
|
RTTI_ExtraLinkedRef, // 0x50,
|
||||||
|
RTTI_ExtraLinkedRefChildren, // 0x51,
|
||||||
|
RTTI_ExtraActivateRef, // 0x52,
|
||||||
|
RTTI_ExtraActivateRefChildren, // 0x53,
|
||||||
|
RTTI_ExtraCanTalkToPlayer, // 0x54,
|
||||||
|
RTTI_ExtraObjectHealth, // 0x55,
|
||||||
|
RTTI_ExtraCellImageSpace, // 0x56,
|
||||||
|
RTTI_ExtraNavMeshPortal, // 0x57,
|
||||||
|
RTTI_ExtraModelSwap, // 0x58,
|
||||||
|
RTTI_ExtraRadius, // 0x59,
|
||||||
|
NULL, // 0x5A,
|
||||||
|
RTTI_ExtraFactionChanges, // 0x5B,
|
||||||
|
RTTI_ExtraDismemberedLimbs, // 0x5C,
|
||||||
|
RTTI_ExtraActorCause, // 0x5D,
|
||||||
|
RTTI_ExtraMultiBound, // 0x5E,
|
||||||
|
NULL, // 0x5F, was ExtraMultiBoundData, removed in 1.7.7.0
|
||||||
|
RTTI_ExtraMultiBoundRef, // 0x60,
|
||||||
|
RTTI_ExtraReflectedRefs, // 0x61,
|
||||||
|
RTTI_ExtraReflectorRefs, // 0x62,
|
||||||
|
RTTI_ExtraEmittanceSource, // 0x63,
|
||||||
|
NULL, // 0x64, was ExtraRadioData, removed in 1.7.7.0
|
||||||
|
RTTI_ExtraCombatStyle, // 0x65,
|
||||||
|
NULL, // 0x66,
|
||||||
|
RTTI_ExtraPrimitive, // 0x67,
|
||||||
|
RTTI_ExtraOpenCloseActivateRef, // 0x68,
|
||||||
|
RTTI_ExtraAnimNoteReceiver, // 0x69,
|
||||||
|
RTTI_ExtraAmmo, // 0x6A,
|
||||||
|
RTTI_ExtraPatrolRefData, // 0x6B,
|
||||||
|
RTTI_ExtraPackageData, // 0x6C,
|
||||||
|
RTTI_ExtraOcclusionShape, // 0x6D,
|
||||||
|
RTTI_ExtraCollisionData, // 0x6E,
|
||||||
|
RTTI_ExtraSayTopicInfoOnceADay, // 0x6F,
|
||||||
|
RTTI_ExtraEncounterZone, // 0x70,
|
||||||
|
RTTI_ExtraSayToTopicInfo, // 0x71,
|
||||||
|
RTTI_ExtraOcclusionPlaneRefData, // 0x72,
|
||||||
|
RTTI_ExtraPortalRefData, // 0x73,
|
||||||
|
RTTI_ExtraPortal, // 0x74,
|
||||||
|
RTTI_ExtraRoom, // 0x75,
|
||||||
|
RTTI_ExtraHealthPerc, // 0x76,
|
||||||
|
RTTI_ExtraRoomRefData, // 0x77,
|
||||||
|
RTTI_ExtraGuardedRefData, // 0x78,
|
||||||
|
RTTI_ExtraCreatureAwakeSound, // 0x79,
|
||||||
|
NULL, // 0x7A,
|
||||||
|
RTTI_ExtraHorse, // 0x7B,
|
||||||
|
RTTI_ExtraIgnoredBySandbox, // 0x7C,
|
||||||
|
RTTI_ExtraCellAcousticSpace, // 0x7D,
|
||||||
|
RTTI_ExtraReservedMarkers, // 0x7E,
|
||||||
|
RTTI_ExtraWeaponIdleSound, // 0x7F,
|
||||||
|
RTTI_ExtraWaterLightRefs, // 0x80,
|
||||||
|
RTTI_ExtraLitWaterRefs, // 0x81,
|
||||||
|
RTTI_ExtraWeaponAttackSound, // 0x82,
|
||||||
|
RTTI_ExtraActivateLoopSound, // 0x83,
|
||||||
|
RTTI_ExtraPatrolRefInUseData, // 0x84,
|
||||||
|
RTTI_ExtraAshPileRef, // 0x85,
|
||||||
|
NULL, // 0x86
|
||||||
|
RTTI_ExtraFollowerSwimBreadcrumbs, // 0x87,
|
||||||
|
RTTI_ExtraAliasInstanceArray, // 0x88,
|
||||||
|
RTTI_ExtraLocation, // 0x89,
|
||||||
|
NULL, // 0x8A,
|
||||||
|
RTTI_ExtraLocationRefType, // 0x8B,
|
||||||
|
RTTI_ExtraPromotedRef, // 0x8C,
|
||||||
|
NULL, // 0x8D,
|
||||||
|
RTTI_ExtraOutfitItem, // 0x8E,
|
||||||
|
NULL, // 0x8F,
|
||||||
|
RTTI_ExtraLeveledItemBase, // 0x90,
|
||||||
|
RTTI_ExtraLightData, // 0x91,
|
||||||
|
RTTI_ExtraSceneData, // 0x92,
|
||||||
|
RTTI_ExtraBadPosition, // 0x93,
|
||||||
|
RTTI_ExtraHeadTrackingWeight, // 0x94,
|
||||||
|
RTTI_ExtraFromAlias, // 0x95,
|
||||||
|
RTTI_ExtraShouldWear, // 0x96,
|
||||||
|
RTTI_ExtraFavorCost, // 0x97,
|
||||||
|
RTTI_ExtraAttachedArrows3D, // 0x98,
|
||||||
|
RTTI_ExtraTextDisplayData, // 0x99,
|
||||||
|
RTTI_ExtraAlphaCutoff, // 0x9A,
|
||||||
|
RTTI_ExtraEnchantment, // 0x9B,
|
||||||
|
RTTI_ExtraSoul, // 0x9C,
|
||||||
|
RTTI_ExtraForcedTarget, // 0x9D,
|
||||||
|
NULL, // 0x9E,
|
||||||
|
RTTI_ExtraUniqueID, // 0x9F,
|
||||||
|
RTTI_ExtraFlags, // 0xA0,
|
||||||
|
RTTI_ExtraRefrPath, // 0xA1,
|
||||||
|
RTTI_ExtraDecalGroup, // 0xA2,
|
||||||
|
RTTI_ExtraLockList, // 0xA3,
|
||||||
|
RTTI_ExtraForcedLandingMarker, // 0xA4,
|
||||||
|
RTTI_ExtraLargeRefOwnerCells, // 0xA5,
|
||||||
|
RTTI_ExtraCellWaterEnvMap, // 0xA6,
|
||||||
|
RTTI_ExtraCellGrassData, // 0xA7,
|
||||||
|
RTTI_ExtraTeleportName, // 0xA8,
|
||||||
|
RTTI_ExtraInteraction, // 0xA9,
|
||||||
|
RTTI_ExtraWaterData, // 0xAA,
|
||||||
|
RTTI_ExtraWaterCurrentZoneData, // 0xAB,
|
||||||
|
RTTI_ExtraAttachRef, // 0xAC,
|
||||||
|
RTTI_ExtraAttachRefChildren, // 0xAD,
|
||||||
|
RTTI_ExtraGroupConstraint, // 0xAE,
|
||||||
|
RTTI_ExtraScriptedAnimDependence, // 0xAF,
|
||||||
|
RTTI_ExtraCachedScale, // 0xB0,
|
||||||
|
RTTI_ExtraRaceData, // 0xB1,
|
||||||
|
RTTI_ExtraGIDBuffer, // 0xB2,
|
||||||
|
RTTI_ExtraMissingRefIDs, // 0xB3
|
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
BSExtraData* BaseExtraList::GetByType(UInt32 type) |
||||||
|
{ |
||||||
|
BSReadLocker locker(&m_lock); |
||||||
|
if (!HasType(type)) return NULL; |
||||||
|
|
||||||
|
const void* rttiType = RTTIForExtraType[type]; |
||||||
|
|
||||||
|
for(BSExtraData * traverse = m_data; traverse; traverse = traverse->next) { |
||||||
|
if (Runtime_DynamicCast((void*)(traverse), RTTI_BSExtraData, rttiType) != NULL) { |
||||||
|
return traverse; |
||||||
|
} |
||||||
|
//if(traverse->type == type)
|
||||||
|
// return traverse;
|
||||||
|
} |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
bool BaseExtraList::Remove(UInt8 type, BSExtraData* toRemove) |
||||||
|
{ |
||||||
|
BSWriteLocker locker(&m_lock); |
||||||
|
if (!toRemove) return false; |
||||||
|
|
||||||
|
if (HasType(type)) { |
||||||
|
bool bRemoved = false; |
||||||
|
if (m_data == toRemove) { |
||||||
|
m_data = m_data->next; |
||||||
|
bRemoved = true; |
||||||
|
} |
||||||
|
|
||||||
|
for (BSExtraData* traverse = m_data; traverse; traverse = traverse->next) { |
||||||
|
if (traverse->next == toRemove) { |
||||||
|
traverse->next = toRemove->next; |
||||||
|
bRemoved = true; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (bRemoved) { |
||||||
|
MarkType(type, true); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool BaseExtraList::Add(UInt8 type, BSExtraData* toAdd) |
||||||
|
{ |
||||||
|
if (!toAdd || HasType(type)) return false; |
||||||
|
|
||||||
|
BSWriteLocker locker(&m_lock); |
||||||
|
BSExtraData* next = m_data; |
||||||
|
m_data = toAdd; |
||||||
|
toAdd->next = next; |
||||||
|
MarkType(type, false); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool BaseExtraList::CheckContainerExtraData(bool isEquipped) |
||||||
|
{ |
||||||
|
return CALL_MEMBER_FN(this, CheckContainerExtraData_Internal)(isEquipped); |
||||||
|
} |
||||||
|
|
||||||
|
const char * BaseExtraList::GetDisplayName(TESForm * type) |
||||||
|
{ |
||||||
|
float healthValue = 1.0; |
||||||
|
|
||||||
|
ExtraHealth* xHealth = static_cast<ExtraHealth*>(GetByType(kExtraData_Health)); |
||||||
|
if(xHealth) |
||||||
|
healthValue = xHealth->health; |
||||||
|
|
||||||
|
ExtraTextDisplayData * xText = CALL_MEMBER_FN(this, GetExtraTextDisplayData_Internal)(); |
||||||
|
if (!xText && healthValue != 1.0) |
||||||
|
{ |
||||||
|
xText = ExtraTextDisplayData::Create(); |
||||||
|
Add(kExtraData_TextDisplayData, xText); |
||||||
|
} |
||||||
|
|
||||||
|
if (xText) |
||||||
|
return xText->GenerateName(type, healthValue); |
||||||
|
else |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
BSExtraData* BSExtraData::Create(UInt32 size, uintptr_t vtbl) |
||||||
|
{ |
||||||
|
void* memory = Heap_Allocate(size); |
||||||
|
memset(memory, 0, size); |
||||||
|
((uintptr_t *)memory)[0] = vtbl; |
||||||
|
BSExtraData* xData = (BSExtraData*)memory; |
||||||
|
return xData; |
||||||
|
} |
@ -0,0 +1,268 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "GameTypes.h" |
||||||
|
#include "skse64_common/Utilities.h" |
||||||
|
|
||||||
|
class ExtraTextDisplayData; |
||||||
|
|
||||||
|
enum ExtraDataType |
||||||
|
{ |
||||||
|
kExtraData_Havok = 0x1, |
||||||
|
kExtraData_Cell3D = 0x2, |
||||||
|
kExtraData_CellWaterType = 0x3, |
||||||
|
kExtraData_RegionList = 0x4, |
||||||
|
kExtraData_SeenData = 0x5, |
||||||
|
kExtraData_EditorID = 0x6, |
||||||
|
kExtraData_CellMusicType = 0x7, |
||||||
|
kExtraData_CellSkyRegion = 0x8, |
||||||
|
kExtraData_ProcessMiddleLow = 0x9, |
||||||
|
kExtraData_DetachTime = 0xA, |
||||||
|
kExtraData_PersistentCell = 0xB, |
||||||
|
// ?? = 0xC,
|
||||||
|
kExtraData_Action = 0xD, |
||||||
|
kExtraData_StartingPosition = 0xE, |
||||||
|
// ?? = 0xF,
|
||||||
|
kExtraData_AnimGraphManager = 0x10, |
||||||
|
// ?? = 0x11,
|
||||||
|
kExtraData_UsedMarkers = 0x12, |
||||||
|
kExtraData_DistantData = 0x13, |
||||||
|
kExtraData_RagDollData = 0x14, |
||||||
|
kExtraData_ContainerChanges = 0x15, |
||||||
|
kExtraData_Worn = 0x16, |
||||||
|
kExtraData_WornLeft = 0x17, |
||||||
|
kExtraData_PackageStartLocation = 0x18, |
||||||
|
kExtraData_Package = 0x19, |
||||||
|
kExtraData_TresPassPackage = 0x1A, |
||||||
|
kExtraData_RunOncePacks = 0x1B, |
||||||
|
kExtraData_ReferenceHandle = 0x1C, |
||||||
|
kExtraData_Follower = 0x1D, |
||||||
|
kExtraData_LevCreaModifier = 0x1E, |
||||||
|
kExtraData_Ghost = 0x1F, |
||||||
|
kExtraData_OriginalReference = 0x20, |
||||||
|
kExtraData_Ownership = 0x21, |
||||||
|
kExtraData_Global = 0x22, |
||||||
|
kExtraData_Rank = 0x23, |
||||||
|
kExtraData_Count = 0x24, |
||||||
|
kExtraData_Health = 0x25, |
||||||
|
// ?? = 0x26,
|
||||||
|
kExtraData_TimeLeft = 0x27, |
||||||
|
kExtraData_Charge = 0x28, |
||||||
|
kExtraData_Light = 0x29, |
||||||
|
kExtraData_Lock = 0x2A, |
||||||
|
kExtraData_Teleport = 0x2B, |
||||||
|
kExtraData_MapMarker = 0x2C, |
||||||
|
kExtraData_LeveledCreature = 0x2D, |
||||||
|
kExtraData_LeveledItem = 0x2E, |
||||||
|
kExtraData_Scale = 0x2F, |
||||||
|
kExtraData_Seed = 0x30, |
||||||
|
kExtraData_MagicCaster = 0x31, // ExtraMagicLight??
|
||||||
|
// ?? = 0x32,
|
||||||
|
// ?? = 0x33,
|
||||||
|
kExtraData_PlayerCrimeList = 0x34, |
||||||
|
// ?? = 0x35,
|
||||||
|
kExtraData_EnableStateParent = 0x36, |
||||||
|
kExtraData_EnableStateChildren = 0x37, |
||||||
|
kExtraData_ItemDropper = 0x38, |
||||||
|
kExtraData_DroppedItemList = 0x39, |
||||||
|
kExtraData_RandomTeleportMarker = 0x3A, |
||||||
|
//?? = 0x3B
|
||||||
|
kExtraData_SavedHavokData = 0x3C, |
||||||
|
kExtraData_CannotWear = 0x3D, |
||||||
|
kExtraData_Poison = 0x3E, |
||||||
|
//?? = 0x3F
|
||||||
|
kExtraData_LastFinishedSequence = 0x40, |
||||||
|
kExtraData_SavedAnimation = 0x41, |
||||||
|
kExtraData_NorthRotation = 0x42, |
||||||
|
kExtraData_SpawnContainer = 0x43, |
||||||
|
kExtraData_FriendHits = 0x44, |
||||||
|
kExtraData_HeadingTarget = 0x45, |
||||||
|
//?? = 0x46
|
||||||
|
kExtraData_RefractionProperty = 0x47, |
||||||
|
kExtraData_StartingWorldOrCell = 0x48, |
||||||
|
kExtraData_Hotkey = 0x49, |
||||||
|
//?? 0x4A
|
||||||
|
kExtraData_EditiorRefMoveData = 0x4B, |
||||||
|
kExtraData_InfoGeneralTopic = 0x4C, |
||||||
|
kExtraData_HasNoRumors = 0x4D, |
||||||
|
kExtraData_Sound = 0x4E, |
||||||
|
kExtraData_TerminalState = 0x4F, |
||||||
|
kExtraData_LinkedRef = 0x50, |
||||||
|
kExtraData_LinkedRefChildren = 0x51, |
||||||
|
kExtraData_ActivateRef = 0x52, |
||||||
|
kExtraData_ActivateRefChildren =0x53, |
||||||
|
kExtraData_CanTalkToPlayer = 0x54, |
||||||
|
kExtraData_ObjectHealth = 0x55, |
||||||
|
kExtraData_CellImageSpace = 0x56, |
||||||
|
kExtraData_NavMeshPortal = 0x57, |
||||||
|
kExtraData_ModelSwap = 0x58, |
||||||
|
kExtraData_Radius = 0x59, |
||||||
|
//?? = 0x5A,
|
||||||
|
kExtraData_FactionChanges = 0x5B, |
||||||
|
kExtraData_DismemberedLimbs = 0x5C, |
||||||
|
kExtraData_ActorCause = 0x5D, |
||||||
|
kExtraData_MultiBound = 0x5E, |
||||||
|
kExtraData_MultiBoundData = 0x5F, |
||||||
|
kExtraData_MultiBoundRef = 0x60, |
||||||
|
kExtraData_ReflectedRefs = 0x61, |
||||||
|
kExtraData_ReflectorRefs = 0x62, |
||||||
|
kExtraData_EmittanceSource = 0x63, |
||||||
|
kExtraData_RadioData = 0x64, |
||||||
|
kExtraData_CombatStyle = 0x65, |
||||||
|
//?? = 0x66,
|
||||||
|
kExtraData_Primitive = 0x67, |
||||||
|
kExtraData_OpenCloseActivateRef = 0x68, |
||||||
|
kExtraData_AnimNoteReceiver = 0x69, |
||||||
|
kExtraData_Ammo = 0x6A, |
||||||
|
kExtraData_PatrolRefData = 0x6B, |
||||||
|
kExtraData_PackageData = 0x6C, |
||||||
|
kExtraData_OcclusionShape = 0x6D, |
||||||
|
kExtraData_CollisionData = 0x6E, |
||||||
|
kExtraData_SayTopicInfoOnceADay = 0x6F, |
||||||
|
kExtraData_EncounterZone = 0x70, |
||||||
|
kExtraData_SayTopicInfo = 0x71, |
||||||
|
kExtraData_OcclusionPlaneRefData = 0x72, |
||||||
|
kExtraData_PortalRefData = 0x73, |
||||||
|
kExtraData_Portal = 0x74, |
||||||
|
kExtraData_Room = 0x75, |
||||||
|
kExtraData_HealthPerc = 0x76, |
||||||
|
kExtraData_RoomRefData = 0x77, |
||||||
|
kExtraData_GuardedRefData = 0x78, |
||||||
|
kExtraData_CreatureAwakeSound = 0x79, |
||||||
|
//?? = 0x7A,
|
||||||
|
kExtraData_Horse = 0x7B, |
||||||
|
kExtraData_IgnoredBySandbox = 0x7C, |
||||||
|
kExtraData_CellAcousticSpace = 0x7D, |
||||||
|
kExtraData_ReservedMarkers = 0x7E, |
||||||
|
kExtraData_WeaponIdleSound = 0x7F, |
||||||
|
kExtraData_WaterLightRefs = 0x80, |
||||||
|
kExtraData_LitWaterRefs = 0x81, |
||||||
|
kExtraData_WeaponAttackSound = 0x82, |
||||||
|
kExtraData_ActivateLoopSound = 0x83, |
||||||
|
kExtraData_PatrolRefInUseData = 0x84, |
||||||
|
kExtraData_AshPileRef = 0x85, |
||||||
|
//?? = 0x86
|
||||||
|
kExtraData_FollowerSwimBreadcrumbs = 0x87, |
||||||
|
kExtraData_AliasInstanceArray = 0x88, |
||||||
|
kExtraData_Location = 0x89, |
||||||
|
//?? = 0x8A,
|
||||||
|
kExtraData_LocationRefType = 0x8B, |
||||||
|
kExtraData_PromotedRef = 0x8C, |
||||||
|
//?? = 0x8D,
|
||||||
|
kExtraData_OutfitItem = 0x8E, |
||||||
|
//?? = 0x8F,
|
||||||
|
kExtraData_LeveledItemBase = 0x90, |
||||||
|
kExtraData_LightData = 0x91, |
||||||
|
kExtraData_SceneData = 0x92, |
||||||
|
kExtraData_BadPosition = 0x93, |
||||||
|
kExtraData_HeadTrackingWeight = 0x94, |
||||||
|
kExtraData_FromAlias = 0x95, |
||||||
|
kExtraData_ShouldWear = 0x96, |
||||||
|
kExtraData_FavorCost = 0x97, |
||||||
|
kExtraData_AttachedArrows3D = 0x98, |
||||||
|
kExtraData_TextDisplayData = 0x99, |
||||||
|
kExtraData_AlphaCutoff = 0x9A, |
||||||
|
kExtraData_Enchantment = 0x9B, |
||||||
|
kExtraData_Soul = 0x9C, |
||||||
|
kExtraData_ForcedTarget = 0x9D, |
||||||
|
//?? = 0x9E,
|
||||||
|
kExtraData_UniqueID = 0x9F, |
||||||
|
kExtraData_Flags = 0xA0, |
||||||
|
kExtraData_RefrPath = 0xA1, |
||||||
|
kExtraData_DecalGroup = 0xA2, |
||||||
|
kExtraData_LockList = 0xA3, |
||||||
|
kExtraData_ForcedLandingMarker = 0xA4, |
||||||
|
kExtraData_LargeRefOwnerCells = 0xA5, |
||||||
|
kExtraData_CellWaterEnvMap = 0xA6, |
||||||
|
kExtraData_CellGrassData = 0xA7, |
||||||
|
kExtraData_TeleportName = 0xA8, |
||||||
|
kExtraData_Interaction = 0xA9, |
||||||
|
kExtraData_WaterData = 0xAA, |
||||||
|
kExtraData_WaterCurrentZoneData = 0xAB, |
||||||
|
kExtraData_AttachRef = 0xAC, |
||||||
|
kExtraData_AttachRefChildren = 0xAD, |
||||||
|
kExtraData_GroupConstraint = 0xAE, |
||||||
|
kExtraData_ScriptedAnimDependence = 0xAF, |
||||||
|
kExtraData_CachedScale = 0xB0, |
||||||
|
kExtraData_RaceData = 0xB1, |
||||||
|
kExtraData_GIDBuffer = 0xB2, |
||||||
|
kExtraData_MissingRefIDs = 0xB3 |
||||||
|
}; |
||||||
|
|
||||||
|
// 10
|
||||||
|
class BSExtraData |
||||||
|
{ |
||||||
|
public: |
||||||
|
BSExtraData(); |
||||||
|
virtual ~BSExtraData(); |
||||||
|
virtual UInt32 GetType(void); |
||||||
|
|
||||||
|
BSExtraData* next; // 08
|
||||||
|
//UInt8 type; // 10
|
||||||
|
//UInt8 padding[3];
|
||||||
|
static BSExtraData* Create(UInt32 size, uintptr_t vtbl); |
||||||
|
}; |
||||||
|
//STATIC_ASSERT(sizeof(BSExtraData) == 0x10);
|
||||||
|
|
||||||
|
// 18
|
||||||
|
class BaseExtraList |
||||||
|
{ |
||||||
|
public: |
||||||
|
BaseExtraList(); |
||||||
|
~BaseExtraList(); |
||||||
|
|
||||||
|
struct PresenceBitfield |
||||||
|
{ |
||||||
|
bool HasType(UInt32 type) const |
||||||
|
{ |
||||||
|
UInt32 index = (type >> 3); |
||||||
|
UInt8 bitMask = 1 << (type % 8); |
||||||
|
return (bits[index] & bitMask) != 0; |
||||||
|
} |
||||||
|
|
||||||
|
UInt8 bits[0x18]; |
||||||
|
}; |
||||||
|
|
||||||
|
bool HasType(UInt32 type) |
||||||
|
{ |
||||||
|
BSReadLocker locker(&m_lock); |
||||||
|
return (m_presence) ? m_presence->HasType(type) : false; |
||||||
|
} |
||||||
|
|
||||||
|
void MarkType(UInt32 type, bool bCleared) |
||||||
|
{ |
||||||
|
UInt32 index = (type >> 3); |
||||||
|
UInt8 bitMask = 1 << (type % 8); |
||||||
|
UInt8& flag = m_presence->bits[index]; |
||||||
|
if (bCleared) { |
||||||
|
flag &= ~bitMask; |
||||||
|
} else { |
||||||
|
flag |= bitMask; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool Remove(UInt8 type, BSExtraData* toRemove); |
||||||
|
bool Add(UInt8 type, BSExtraData* toAdd); |
||||||
|
|
||||||
|
bool CheckContainerExtraData(bool isEquipped); |
||||||
|
|
||||||
|
const char * GetDisplayName(TESForm * type); |
||||||
|
|
||||||
|
BSExtraData* GetByType(UInt32 type); |
||||||
|
BSExtraData * m_data; // 00
|
||||||
|
PresenceBitfield * m_presence; // 08
|
||||||
|
|
||||||
|
// These added in SE
|
||||||
|
BSReadWriteLock m_lock; |
||||||
|
|
||||||
|
private: |
||||||
|
MEMBER_FN_PREFIX(BaseExtraList); |
||||||
|
// 6AE109C256B98466C001B25B75BD48FB62F884B1+5A
|
||||||
|
DEFINE_MEMBER_FN(CheckContainerExtraData_Internal, bool, 0x0010CC40, bool isEquipped); |
||||||
|
// This also does some internal ReferenceHandle lookup
|
||||||
|
// B995A21984B048C2B4F61777E615FFFB2806F9B7
|
||||||
|
DEFINE_MEMBER_FN(GetExtraTextDisplayData_Internal, ExtraTextDisplayData*, 0x00111420); |
||||||
|
}; |
||||||
|
|
||||||
|
typedef tList<BaseExtraList> ExtendDataList; |
||||||
|
|
||||||
|
STATIC_ASSERT(sizeof(BaseExtraList) == 0x18); |
@ -0,0 +1,27 @@ |
|||||||
|
#include "GameCamera.h" |
||||||
|
|
||||||
|
void LocalMapCamera::SetDefaultStateMinFrustumDimensions(float width, float height) |
||||||
|
{ |
||||||
|
defaultState->minFrustumWidth = width / 2.0; |
||||||
|
defaultState->minFrustumHeight = height / 2.0; |
||||||
|
} |
||||||
|
|
||||||
|
void LocalMapCamera::SetAreaBounds(NiPoint3 * maxBound, NiPoint3 * minBound) |
||||||
|
{ |
||||||
|
areaBoundsMin = *minBound; |
||||||
|
areaBoundsMax = *maxBound; |
||||||
|
areaBoundsMax.z += (*g_mapLocalHeight); |
||||||
|
} |
||||||
|
|
||||||
|
void LocalMapCamera::SetDefaultStateMaxBound(NiPoint3 * maxBound) |
||||||
|
{ |
||||||
|
defaultState->someBoundMax = *maxBound; |
||||||
|
defaultState->someBoundMax.z += (*g_mapLocalHeight); |
||||||
|
} |
||||||
|
|
||||||
|
void LocalMapCamera::SetDefaultStateBounds(float x, float y, float z) |
||||||
|
{ |
||||||
|
defaultState->someBoundMin.x = x - defaultState->someBoundMax.x; |
||||||
|
defaultState->someBoundMin.y = y - defaultState->someBoundMax.y; |
||||||
|
defaultState->someBoundMin.z = z - defaultState->someBoundMax.z; |
||||||
|
} |
@ -0,0 +1,387 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "GameTypes.h" |
||||||
|
#include "GameInput.h" |
||||||
|
|
||||||
|
#include "GameSettings.h" |
||||||
|
|
||||||
|
#include "skse64/NiObjects.h" |
||||||
|
#include "skse64/NiTypes.h" |
||||||
|
|
||||||
|
class TESCamera; |
||||||
|
class NiNode; |
||||||
|
|
||||||
|
// 20
|
||||||
|
class TESCameraState |
||||||
|
{ |
||||||
|
public: |
||||||
|
TESCameraState(); |
||||||
|
virtual ~TESCameraState(); |
||||||
|
|
||||||
|
virtual void OnStateStart(); // pure
|
||||||
|
virtual void OnStateEnd(); // pure
|
||||||
|
virtual void OnUpdate(void * unk1); |
||||||
|
virtual void Unk_04(); |
||||||
|
virtual void Unk_05(); |
||||||
|
virtual void Unk_06(); // pure
|
||||||
|
virtual void Unk_07(); // pure
|
||||||
|
virtual void Unk_08(); // pure
|
||||||
|
|
||||||
|
BSIntrusiveRefCounted refCount; // 08
|
||||||
|
TESCamera * camera; // 10
|
||||||
|
UInt32 stateId; // 18
|
||||||
|
UInt32 pad1C; // 1C
|
||||||
|
}; |
||||||
|
|
||||||
|
// 90
|
||||||
|
class FirstPersonState : public TESCameraState |
||||||
|
{ |
||||||
|
public: |
||||||
|
FirstPersonState(); |
||||||
|
virtual ~FirstPersonState(); |
||||||
|
|
||||||
|
PlayerInputHandler inputHandler; // 20
|
||||||
|
float unk30[6]; // 30
|
||||||
|
UInt64 unk48; // 48
|
||||||
|
UInt64 unk50; // 50
|
||||||
|
void* unk58; // 58
|
||||||
|
void* unk60; // 60
|
||||||
|
float unk68[3]; // 70
|
||||||
|
UInt32 unk74; // 74
|
||||||
|
UInt32 unk78; // 78
|
||||||
|
float unk7C; // 7C
|
||||||
|
UInt32 unk80; // 80
|
||||||
|
UInt8 unk84[4]; // 84
|
||||||
|
UInt64 unk88; // 88
|
||||||
|
}; |
||||||
|
STATIC_ASSERT(sizeof(FirstPersonState) == 0x90); |
||||||
|
|
||||||
|
// E8
|
||||||
|
class ThirdPersonState : public TESCameraState |
||||||
|
{ |
||||||
|
public: |
||||||
|
ThirdPersonState(); |
||||||
|
virtual ~ThirdPersonState(); |
||||||
|
virtual void Unk_09(void); |
||||||
|
virtual void Unk_0A(void); |
||||||
|
virtual void UpdateMode(bool weaponDrawn); |
||||||
|
|
||||||
|
PlayerInputHandler inputHandler; // 20
|
||||||
|
NiNode * cameraNode; // 30
|
||||||
|
NiNode * controllerNode; // 38
|
||||||
|
float unk40[4]; // 40
|
||||||
|
UInt32 unk50[3]; // 50
|
||||||
|
float fOverShoulderPosX; // 5C
|
||||||
|
float fOverShoulderCombatAddY; // 60
|
||||||
|
float fOverShoulderPosZ; // 64
|
||||||
|
float unk68[3]; // 68
|
||||||
|
UInt32 unk74[6]; // 74
|
||||||
|
float unk8C; // 8C - init'd 7F7FFFFF
|
||||||
|
UInt32 unk90[3]; // 90
|
||||||
|
float unk9C; // 9C - init'd 7F7FFFFF
|
||||||
|
UInt64 unkA0; // A0
|
||||||
|
UInt64 unkA8; // A8
|
||||||
|
float unkB0; // B0
|
||||||
|
UInt32 unkB4[3]; // B4
|
||||||
|
float unkC0[6]; // C0
|
||||||
|
UInt32 unkD8; // D8
|
||||||
|
UInt8 unkDC[7]; // DC
|
||||||
|
UInt8 padE3[5]; // E3
|
||||||
|
}; |
||||||
|
STATIC_ASSERT(sizeof(ThirdPersonState) == 0xE8); |
||||||
|
|
||||||
|
// 110
|
||||||
|
class DragonCameraState : public ThirdPersonState |
||||||
|
{ |
||||||
|
public: |
||||||
|
DragonCameraState(); |
||||||
|
virtual ~DragonCameraState(); |
||||||
|
|
||||||
|
UInt32 unkE8; // 0E8
|
||||||
|
UInt32 unkEC; // 0EC
|
||||||
|
UInt8 unkF0; // 0F0
|
||||||
|
UInt8 padF1[3]; // 0F1
|
||||||
|
float unkF4; // 0F4 - init'd to 1
|
||||||
|
UInt8 unkF8; // 0F8
|
||||||
|
UInt8 padF9[3]; // 0F9
|
||||||
|
float unkFC[4]; // 0FC
|
||||||
|
UInt32 unk10C; // 10C
|
||||||
|
}; |
||||||
|
|
||||||
|
// F8
|
||||||
|
class HorseCameraState : public ThirdPersonState |
||||||
|
{ |
||||||
|
public: |
||||||
|
HorseCameraState(); |
||||||
|
virtual ~HorseCameraState(); |
||||||
|
|
||||||
|
UInt32 unkE8; // E8
|
||||||
|
UInt32 unkEC; // EC
|
||||||
|
UInt8 unkF0; // F0
|
||||||
|
UInt8 padF1[7]; // F1
|
||||||
|
}; |
||||||
|
|
||||||
|
// 50
|
||||||
|
class TweenMenuCameraState : public TESCameraState |
||||||
|
{ |
||||||
|
public: |
||||||
|
TweenMenuCameraState(); |
||||||
|
virtual ~TweenMenuCameraState(); |
||||||
|
|
||||||
|
float unk20[4]; // 20
|
||||||
|
UInt32 unk30; // 30
|
||||||
|
float unk34[4]; // 34
|
||||||
|
UInt32 unk44; // 44
|
||||||
|
UInt32 unk48; // 48
|
||||||
|
UInt8 unk4C; // 4C
|
||||||
|
UInt8 pad4D[3]; // 4D
|
||||||
|
}; |
||||||
|
|
||||||
|
// 38
|
||||||
|
class VATSCameraState : public TESCameraState |
||||||
|
{ |
||||||
|
public: |
||||||
|
VATSCameraState(); |
||||||
|
virtual ~VATSCameraState(); |
||||||
|
|
||||||
|
float unk20[6]; // 20
|
||||||
|
}; |
||||||
|
|
||||||
|
// 50
|
||||||
|
class FreeCameraState : public TESCameraState |
||||||
|
{ |
||||||
|
public: |
||||||
|
FreeCameraState(); |
||||||
|
virtual ~FreeCameraState(); |
||||||
|
|
||||||
|
PlayerInputHandler inputHandler; // 20
|
||||||
|
float unk30[7]; // 30
|
||||||
|
UInt32 unk4C; // 4C
|
||||||
|
}; |
||||||
|
|
||||||
|
// 28
|
||||||
|
class AutoVanityState : public TESCameraState |
||||||
|
{ |
||||||
|
public: |
||||||
|
AutoVanityState(); |
||||||
|
virtual ~AutoVanityState(); |
||||||
|
|
||||||
|
UInt32 unk20; // 20
|
||||||
|
UInt32 pad24; // 24
|
||||||
|
}; |
||||||
|
|
||||||
|
// 40
|
||||||
|
class FurnitureCameraState : public TESCameraState |
||||||
|
{ |
||||||
|
public: |
||||||
|
FurnitureCameraState(); |
||||||
|
virtual ~FurnitureCameraState(); |
||||||
|
|
||||||
|
UInt32 unk20; // 20
|
||||||
|
float unk24; // 24
|
||||||
|
float unk28; // 28
|
||||||
|
float unk2C; // 2C
|
||||||
|
UInt32 unk30; // 30
|
||||||
|
UInt32 unk34; // 34
|
||||||
|
UInt32 unk38; // 38
|
||||||
|
UInt8 unk3C; // 3C
|
||||||
|
UInt8 unk3D; // 3D
|
||||||
|
UInt8 unk3E; // 3E
|
||||||
|
UInt8 pad3F; // 3F
|
||||||
|
}; |
||||||
|
|
||||||
|
// 28
|
||||||
|
class IronSightsState : public TESCameraState |
||||||
|
{ |
||||||
|
public: |
||||||
|
IronSightsState(); |
||||||
|
virtual ~IronSightsState(); |
||||||
|
|
||||||
|
UInt64 unk20; // 20
|
||||||
|
}; |
||||||
|
|
||||||
|
// 138
|
||||||
|
class BleedoutCameraState : public ThirdPersonState |
||||||
|
{ |
||||||
|
public: |
||||||
|
BleedoutCameraState(); |
||||||
|
virtual ~BleedoutCameraState(); |
||||||
|
|
||||||
|
float unkE8[8]; // E8
|
||||||
|
UInt32 unk108; // 108
|
||||||
|
float unk10C; // 10C - init'd to 200
|
||||||
|
float unk110; // 110 - init'd to 0.523599 (PI/6)
|
||||||
|
UInt32 unk114; // 114
|
||||||
|
float unk118; // 118
|
||||||
|
UInt32 pad11C; // 11C
|
||||||
|
UInt64 unk120; // 120
|
||||||
|
UInt32 unk128; // 128 - init'd to FFFFFFFF
|
||||||
|
UInt8 unk12C; // 12C
|
||||||
|
UInt8 pad12D[3]; // 12D
|
||||||
|
UInt32 unk130; // 130
|
||||||
|
UInt8 unk134; // 134
|
||||||
|
UInt8 pad135[3]; // 135
|
||||||
|
}; |
||||||
|
|
||||||
|
// 40
|
||||||
|
class PlayerCameraTransitionState : public TESCameraState |
||||||
|
{ |
||||||
|
public: |
||||||
|
PlayerCameraTransitionState(); |
||||||
|
virtual ~PlayerCameraTransitionState(); |
||||||
|
|
||||||
|
UInt32 unk20; // 20
|
||||||
|
UInt32 unk24; // 24
|
||||||
|
UInt64 unk28; // 28
|
||||||
|
UInt64 unk30; // 30
|
||||||
|
UInt32 unk38; // 38
|
||||||
|
UInt8 unk3C; // 3C
|
||||||
|
UInt8 unk3D; // 3D
|
||||||
|
UInt16 pad3E; |
||||||
|
}; |
||||||
|
|
||||||
|
// 38
|
||||||
|
class TESCamera |
||||||
|
{ |
||||||
|
public: |
||||||
|
TESCamera(); |
||||||
|
virtual ~TESCamera(); |
||||||
|
|
||||||
|
virtual void SetNode(NiNode * node); |
||||||
|
virtual void Update(); |
||||||
|
|
||||||
|
float rotZ; // 08
|
||||||
|
float rotX; // 0C
|
||||||
|
NiPoint3 pos; // 10
|
||||||
|
float zoom; // 1C
|
||||||
|
NiNode * cameraNode; // 20 - First child is usually NiCamera
|
||||||
|
TESCameraState * cameraState; // 28
|
||||||
|
UInt8 unk30; // 30
|
||||||
|
UInt8 pad31[7]; // 31
|
||||||
|
|
||||||
|
MEMBER_FN_PREFIX(TESCamera); |
||||||
|
DEFINE_MEMBER_FN(SetCameraState, UInt32, 0x004F5C80, TESCameraState * cameraState); |
||||||
|
}; |
||||||
|
STATIC_ASSERT(offsetof(TESCamera, cameraNode) == 0x20); |
||||||
|
STATIC_ASSERT(sizeof(TESCamera) == 0x38); |
||||||
|
|
||||||
|
// 68
|
||||||
|
class LocalMapCamera : public TESCamera |
||||||
|
{ |
||||||
|
public: |
||||||
|
LocalMapCamera(); |
||||||
|
virtual ~LocalMapCamera(); |
||||||
|
|
||||||
|
// 48
|
||||||
|
class DefaultState : public TESCameraState |
||||||
|
{ |
||||||
|
public: |
||||||
|
NiPoint3 someBoundMax; // 20
|
||||||
|
NiPoint3 someBoundMin; // 2C
|
||||||
|
float zoomPercent; // 38
|
||||||
|
float minFrustumWidth; // 3C
|
||||||
|
float minFrustumHeight; // 40
|
||||||
|
UInt32 pad44; // 44
|
||||||
|
}; |
||||||
|
|
||||||
|
NiPoint3 areaBoundsMax; // 38
|
||||||
|
NiPoint3 areaBoundsMin; // 44
|
||||||
|
DefaultState * defaultState; // 50
|
||||||
|
NiObject * niCamera; // 58
|
||||||
|
float northRotation; // 60
|
||||||
|
UInt32 pad64; // 64
|
||||||
|
|
||||||
|
void SetDefaultStateMinFrustumDimensions(float width, float height); |
||||||
|
void SetAreaBounds(NiPoint3 * maxBound, NiPoint3 * minBound); |
||||||
|
void SetDefaultStateMaxBound(NiPoint3 * maxBound); |
||||||
|
void SetDefaultStateBounds(float x, float y, float z); |
||||||
|
|
||||||
|
MEMBER_FN_PREFIX(LocalMapCamera); |
||||||
|
DEFINE_MEMBER_FN(ctor, void, 0x001F5390); |
||||||
|
DEFINE_MEMBER_FN(SetNorthRotation, void, 0x001F5750, float northRotation); |
||||||
|
}; |
||||||
|
|
||||||
|
STATIC_ASSERT(offsetof(LocalMapCamera, northRotation) == 0x60); |
||||||
|
|
||||||
|
// 90
|
||||||
|
class MapCamera : public TESCamera |
||||||
|
{ |
||||||
|
public: |
||||||
|
MapCamera(); |
||||||
|
virtual ~MapCamera(); |
||||||
|
|
||||||
|
float unk38[5]; // 38
|
||||||
|
UInt32 unk4C[3]; // 4C
|
||||||
|
UInt64 unk58; // 58
|
||||||
|
UInt32 unk60; // 60
|
||||||
|
UInt32 unk64; // 64
|
||||||
|
UInt64 unk68[2]; // 68
|
||||||
|
UInt64 unk78; // 78
|
||||||
|
UInt64 unk80; // 80
|
||||||
|
UInt8 unk88; // 88
|
||||||
|
UInt8 pad89[7]; // 89
|
||||||
|
}; |
||||||
|
|
||||||
|
// 38
|
||||||
|
class RaceSexCamera : public TESCamera |
||||||
|
{ |
||||||
|
public: |
||||||
|
RaceSexCamera(); |
||||||
|
virtual ~RaceSexCamera(); |
||||||
|
}; |
||||||
|
|
||||||
|
// 168
|
||||||
|
class PlayerCamera : public TESCamera |
||||||
|
{ |
||||||
|
public: |
||||||
|
PlayerCamera(); |
||||||
|
virtual ~PlayerCamera(); |
||||||
|
|
||||||
|
static PlayerCamera * GetSingleton(void) |
||||||
|
{ |
||||||
|
// 0FAF5D3C755F11266ECC496FD392A0A2EA23403B+37
|
||||||
|
static RelocPtr<PlayerCamera*> g_playerCamera(0x02EC59B8); |
||||||
|
return *g_playerCamera; |
||||||
|
} |
||||||
|
|
||||||
|
enum |
||||||
|
{ |
||||||
|
kCameraState_FirstPerson = 0, |
||||||
|
kCameraState_AutoVanity, |
||||||
|
kCameraState_VATS, |
||||||
|
kCameraState_Free, |
||||||
|
kCameraState_IronSights, |
||||||
|
kCameraState_Furniture, |
||||||
|
kCameraState_Transition, |
||||||
|
kCameraState_TweenMenu, |
||||||
|
kCameraState_ThirdPerson1, |
||||||
|
kCameraState_ThirdPerson2, |
||||||
|
kCameraState_Horse, |
||||||
|
kCameraState_Bleedout, |
||||||
|
kCameraState_Dragon, |
||||||
|
kNumCameraStates |
||||||
|
}; |
||||||
|
|
||||||
|
UInt8 unk38[0xB8-0x38]; // 028
|
||||||
|
TESCameraState * cameraStates[kNumCameraStates]; // 0B8
|
||||||
|
UInt64 unk120; // 120
|
||||||
|
UInt64 unk128; // 128
|
||||||
|
UInt64 unk130; // 130
|
||||||
|
UInt32 unk138; // 138
|
||||||
|
float worldFOV; // 13C
|
||||||
|
float firstPersonFOV; // 140
|
||||||
|
UInt8 unk144[0x160-0x144]; // 144
|
||||||
|
UInt8 unk160; // 160
|
||||||
|
UInt8 unk161; // 161
|
||||||
|
UInt8 unk162; // 162 - init'd to 1
|
||||||
|
UInt8 unk163; // 163
|
||||||
|
UInt8 unk164; // 164
|
||||||
|
UInt8 unk165; // 165
|
||||||
|
UInt8 pad166[2]; // 166
|
||||||
|
|
||||||
|
MEMBER_FN_PREFIX(PlayerCamera); |
||||||
|
DEFINE_MEMBER_FN(UpdateThirdPerson, void, 0x0084D630, bool weaponDrawn); |
||||||
|
}; |
||||||
|
|
||||||
|
STATIC_ASSERT(offsetof(PlayerCamera, cameraStates) == 0xB8); |
||||||
|
STATIC_ASSERT(offsetof(PlayerCamera, pad166) == 0x166); |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue