Tiberian Technologies Scripts Reference Revision: 9000
Loading...
Searching...
No Matches
Defines.h
1/* Renegade Scripts.dll
2 Copyright 2013 Tiberian Technologies
3
4 This file is part of the Renegade scripts.dll
5 The Renegade scripts.dll is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 2, or (at your option) any later
8 version. See the file COPYING for more details.
9 In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence.
10 Only the source code to the module(s) containing the licenced code has to be released.
11*/
12#ifndef TT_INCLUDE__DEFINES_H
13#define TT_INCLUDE__DEFINES_H
14
15// put global defines here
16
17#include "Types.h"
18#include "stdarg.h"
19#if (WWCONFIG) || (TDBEDIT) || (W3DSHADER) || (W3DLIB_EXPORTS) || (W3DMESHMENDER) || (W3DDEPENDS) || (W3DMAPPER) || (ACHASH) || (PACKAGEEDITOR) || (FIXPLANES) || (MERGELOD) || (MIXCHECK) || (DDBEDIT) || (MAKEMIX) || (ALTMAT) || (W3DVIEWER)
20#define EXTERNAL 1
21#endif
22
23#pragma warning(disable: 4100) // unreferenced formal parameter
24#pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union
25#pragma warning(disable: 4505) // unreferenced local function has been removed
26#pragma warning(disable: 6509) // warning c6509: Return used on precondition
27
28//class needs to have dll-interface to used by clients of class. Except that it doesn't.
29//If it did, the linker would complain.
30#pragma warning(disable:4251)
31
32#define WIN32_LEAN_AND_MEAN
33#define _WIN32_WINNT 0x0601
34#define _USE_MATH_DEFINES
35
36// breakpoint
37#if defined(_M_IX86)
38#define TT_INTERRUPT { __asm { __asm int 3 } }
39#elif defined(_M_AMD64)
40#define TT_INTERRUPT { __debugbreak(); }
41#endif
42
43// assert that is not removed in release mode
44#define TT_RELEASE_ASSERT(expression) { __analysis_assume(expression); if (!(expression)) TT_INTERRUPT; }
45
46// assert
47#ifdef DEBUG
48# define TT_ASSERT(expression) \
49 { \
50 __analysis_assume(expression); \
51 if (!(expression)) \
52 TT_INTERRUPT; \
53 }
54#else
55# define TT_ASSERT(expression) \
56 { \
57 __analysis_assume(expression); \
58 }
59#endif
60
61// assumption optimization
62#ifdef DEBUG
63# define TT_ASSUME(x) TT_ASSERT(x)
64#elif defined(NDEBUG) && defined(_MSC_VER)
65# define TT_ASSUME(x) __assume(x)
66#else
67# define TT_ASSUME(x)
68#endif
69
70// unreachable code
71# ifdef DEBUG
72# define TT_UNREACHABLE TT_INTERRUPT
73# else
74# define TT_UNREACHABLE __assume(false);
75# endif
76
77#define TT_UNIMPLEMENTED TT_INTERRUPT
78#define TT_UNTESTED TT_INTERRUPT
79
80// deprecated code
81#define TT_DEPRECATED(x) __declspec(deprecated(x))
82
83// inlined function calls
84#if defined(NDEBUG) && defined(_MSC_VER)
85# define TT_INLINE __forceinline
86#else
87# define TT_INLINE inline
88#endif
89
90// countof for static array
91template <typename T, size_t N>
92char ( &_ArraySizeHelper( T (&array)[N] ))[N];
93
94#define countof( array ) (sizeof( _ArraySizeHelper( array ) ))
95
96// This can be used as a workaround for when a template type in a class is needed.
97// something like MACRO(Class<Param1, Param2>) will make the preprocessor think two
98// parameters are supplied ("Class<Param1" and "Param2>").
99#define TT_NOOP(...) __VA_ARGS__
100
101// unknown type
102#define UNK TT_DEPRECATED("Unknown type") uint32
103#define UNKB TT_DEPRECATED("Unknown type") uint8
104#define UNKADDRESS 0x00000000
105
106// to communicate with Renegade
107#ifndef EXTERNAL
108
109#ifdef SHARED_EXPORTS
110# define SHARED_API __declspec(dllexport)
111#else
112# define SHARED_API __declspec(dllimport)
113#endif
114
115#ifdef SSGM
116# define SCRIPTS_API __declspec(dllexport)
117#else
118# ifdef SSGMPLUGIN
119# define SCRIPTS_API __declspec(dllimport)
120# else
121# define SCRIPTS_API
122# endif
123#endif
124
125template <typename T> T& ResolveGameReference(const int client, const int server, const int leveledit)
126{
127 if (Exe == 6) InitEngine();
128#pragma warning(suppress: 6011) //warning C6011: dereferencing NULL pointer <name>
129 return *((T*)((Exe == 0) ? client : ((Exe == 1) ? server : ((Exe == 4) ? leveledit : 0))));
130};
131
132template <typename T, const int size> class RefArrayHelper
133{
134protected:
135 char _dummy[size * sizeof(T)];
136public:
137 operator T* ()
138 {
139 return (T*) this;
140 };
141
142 operator const T* () const
143 {
144 return (T*) this;
145 };
146
147 T* operator & ()
148 {
149 return (T*) this;
150 };
151
152 const T* operator & () const
153 {
154 return (T*) this;
155 };
156};
157
158
159#define REF_DECL(type, name) type & name
160#define REF_ARR_DECL(type, name, size) RefArrayHelper<type, size> & name
161
162#ifndef TTLE_EXPORTS
163#define REF_DEF2(type, name, client, server) type & name = ResolveGameReference<type>(client, server, 0)
164#define REF_ARR_DEF2(type, name, size, client, server) RefArrayHelper<type, size> & name = ResolveGameReference<RefArrayHelper< type, size >> (client, server, 0)
165#endif //TTLE_EXPORTS
166
167#define REF_DEF3(type, name, client, server, leveledit) type & name = ResolveGameReference<type>(client, server, leveledit)
168#define REF_ARR_DEF3(type, name, size, client, server, leveledit) RefArrayHelper<type, size> & name = ResolveGameReference<RefArrayHelper< type, size >> ( client, server, leveledit)
169
170
171
172// Q: So what are these ATx things anyways?
173// A: The ATx macros are are designed for transparently calling functions that may have
174// multiple implementations depending on the current system configuration. The most
175// common use of them that you'll see is calling functions inside Renegade. They work
176// by dynamically rewriting code in order to call the proper function with little
177// to no overhead, so do not modify them unless you *really* know what you are doing.
178//
179// Q: And I use them how exactly?
180// A: For ATx, make sure the function is declared with RENEGADE_FUNCTION and
181// then use ATx as the function implemention.
182//
183// Examples:
184// RENEGADE_FUNCTION void ExampleFunction2() AT2(0xdeadbeef, 0xbaadf00d);
185// RENEGADE_FUNCTION void ExampleFunction3() AT3(0xdeadbeef, 0xbaadf00d, 0xdeadc0de);
186
187#ifndef SSGMPLUGIN
188void* HookupAT3(void* a, void* b, void* c, void* patch_start);
189#define RENEGADE_FUNCTION __declspec(naked)
190#ifndef TTLE_EXPORTS
191#define AT2(client, server) AT3(client, server, 0)
192#endif
193#define AT3(client, server, leveledit) \
194{ \
195 __asm AT3PatchStart: \
196 __asm push ecx \
197 __asm push edx \
198 __asm push offset AT3PatchStart \
199 __asm push leveledit \
200 __asm push server \
201 __asm push client \
202 __asm call HookupAT3 \
203 __asm add esp, 16 \
204 __asm pop edx \
205 __asm pop ecx \
206 __asm jmp eax \
207}
208void InitEngine();
209extern int Exe; // used by Vx()/ATx() macros
210#endif
211
212#else
213#define SCRIPTS_API
214#define SHARED_API
215#endif
216
217template<int stackBufferLength, typename Char> class FormattedString;
218
219template<int stackBufferLength> class FormattedString<stackBufferLength, char>
220{
221
222public:
223
224 char stackBuffer[stackBufferLength+1];
225 char* heapBuffer;
226 const char* value;
227 int length;
228
229 FormattedString(const char* format, ...)
230 {
231 va_list arguments;
232 va_start(arguments, format);
233 length = vsnprintf(stackBuffer, stackBufferLength, format, arguments);
234 if (length >= 0)
235 {
236 // The formatted string fit on the stack. Use the stack buffer.
237 stackBuffer[length] = '\0'; // Fix terminator. Only necessary if length == stackBufferLength.
238 heapBuffer = 0;
239 value = stackBuffer;
240 }
241 else
242 {
243 // The formatted string did not fit on the stack. Allocate a heap buffer.
244 length = _vscprintf(format, arguments);
245 heapBuffer = new char[length + 1];
246 vsprintf(heapBuffer, format, arguments);
247 value = heapBuffer;
248 }
249 va_end(arguments);
250 }
251
252 ~FormattedString()
253 {
254 delete[] heapBuffer;
255 }
256
257 const char* getValue() const { return value; }
258 const int getLength() const { return length; }
259};
260
261template<int stackBufferLength> class FormattedString<stackBufferLength, wchar_t>
262{
263
264public:
265
266 wchar_t stackBuffer[stackBufferLength+1];
267 wchar_t* heapBuffer;
268 const wchar_t* value;
269 int length;
270
271 FormattedString(const wchar_t* format, ...)
272 {
273 va_list arguments;
274 va_start(arguments, format);
275 length = _vsnwprintf(stackBuffer, stackBufferLength, format, arguments);
276 if (length >= 0)
277 {
278 // The formatted string fit on the stack. Use the stack buffer.
279 stackBuffer[length] = '\0'; // Fix terminator. Only necessary if length == stackBufferLength.
280 heapBuffer = 0;
281 value = stackBuffer;
282 }
283 else
284 {
285 // The formatted string did not fit on the stack. Allocate a heap buffer.
286 length = _vscwprintf(format, arguments);
287 heapBuffer = new wchar_t[length + 1];
288 _vsnwprintf(heapBuffer, length + 1, format, arguments);
289 value = heapBuffer;
290 }
291 va_end(arguments);
292 }
293
294 ~FormattedString()
295 {
296 delete[] heapBuffer;
297 }
298
299 const wchar_t* getValue() const { return value; }
300 const int getLength() const { return length; }
301};
302
303// Format a string (sprintf style) using a stack buffer of a given size if possible, or a heap buffer otherwise.
304#define TT_FORMAT(maxFormattedLength, format, ...) FormattedString<maxFormattedLength, char>(format, __VA_ARGS__).getValue()
305#define TT_FORMAT_WIDE(maxFormattedLength, format, ...) FormattedString<maxFormattedLength, wchar_t>(format, __VA_ARGS__).getValue()
306
307// Define the possible values for the Exe variable, rather than scattering magic numbers throughout the code
308#define EXE_CLIENT 0
309#define EXE_SERVER 1
310#define EXE_LEVELEDIT 4
311#define EXE_UNINITIALISED 6
312
313#endif