1 /*
2 	C-Dogs SDL
3 	A port of the legendary (and fun) action/arcade cdogs.
4 	Copyright (C) 1995 Ronny Wester
5 	Copyright (C) 2003 Jeremy Chin
6 	Copyright (C) 2003-2007 Lucas Martin-King
7 
8 	This program is free software; you can redistribute it and/or modify
9 	it under the terms of the GNU General Public License as published by
10 	the Free Software Foundation; either version 2 of the License, or
11 	(at your option) any later version.
12 
13 	This program is distributed in the hope that it will be useful,
14 	but WITHOUT ANY WARRANTY; without even the implied warranty of
15 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 	GNU General Public License for more details.
17 
18 	You should have received a copy of the GNU General Public License
19 	along with this program; if not, write to the Free Software
20 	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 
22 	This file incorporates work covered by the following copyright and
23 	permission notice:
24 
25 	Copyright (c) 2013-2017, 2019-2021 Cong Xu
26 	All rights reserved.
27 
28 	Redistribution and use in source and binary forms, with or without
29 	modification, are permitted provided that the following conditions are met:
30 
31 	Redistributions of source code must retain the above copyright notice, this
32 	list of conditions and the following disclaimer.
33 	Redistributions in binary form must reproduce the above copyright notice,
34 	this list of conditions and the following disclaimer in the documentation
35 	and/or other materials provided with the distribution.
36 
37 	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
38 	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40 	ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
41 	LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43 	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
44 	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
45 	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47 	POSSIBILITY OF SUCH DAMAGE.
48 */
49 #pragma once
50 
51 #include <assert.h>
52 #include <stdbool.h>
53 #include <stdio.h> /* for stderr */
54 #include <stdlib.h>
55 #include <string.h>
56 
57 #include "color.h"
58 #include "sys_specifics.h"
59 
60 // Global variables so their address can be taken (passed into void * funcs)
61 extern bool gTrue;
62 extern bool gFalse;
63 
64 #define STRINGIFY(x) #x
65 #define TOSTRING(x) STRINGIFY(x)
66 
67 #ifdef _MSC_VER
68 #define CHALT() __debugbreak()
69 #else
70 #define CHALT()
71 #endif
72 
73 #define CASSERT(_x, _errmsg)                                                  \
74 	{                                                                         \
75 		volatile bool isOk = _x;                                              \
76 		if (!isOk)                                                            \
77 		{                                                                     \
78 			static char _buf[1024];                                           \
79 			sprintf(                                                          \
80 				_buf, "In %s %d:%s: " _errmsg " (" #_x ")", __FILE__,         \
81 				__LINE__, __func__);                                          \
82 			CHALT();                                                          \
83 			assert(_x);                                                       \
84 		}                                                                     \
85 	}
86 
87 // Even though malloc(0) may return NULL, we don't account for it for
88 // simplicity and to allow code linters to work better
89 #define _CCHECKALLOC(_func, _var, _size)                                      \
90 	{                                                                         \
91 		if (_var == NULL)                                                     \
92 		{                                                                     \
93 			exit(1);                                                          \
94 		}                                                                     \
95 	}
96 
97 #define CMALLOC(_var, _size)                                                  \
98 	{                                                                         \
99 		_var = malloc(_size);                                                 \
100 		_CCHECKALLOC("CMALLOC", _var, (_size))                                \
101 	}
102 #define CCALLOC(_var, _size)                                                  \
103 	{                                                                         \
104 		_var = calloc(1, _size);                                              \
105 		_CCHECKALLOC("CCALLOC", _var, (_size))                                \
106 	}
107 #define CREALLOC(_var, _size)                                                 \
108 	{                                                                         \
109 		_var = realloc(_var, _size);                                          \
110 		_CCHECKALLOC("CREALLOC", _var, (_size))                               \
111 	}
112 #define CSTRDUP(_var, _str)                                                   \
113 	{                                                                         \
114 		CMALLOC(_var, strlen(_str) + 1);                                      \
115 		strcpy(_var, _str);                                                   \
116 	}
117 
118 #define CFREE(_var)                                                           \
119 	{                                                                         \
120 		free(_var);                                                           \
121 	}
122 
123 #define UNUSED(expr) (void)(expr);
124 
125 #ifndef MAX
126 #define MAX(x, y) ((x) > (y) ? (x) : (y))
127 #endif
128 #ifndef MIN
129 #define MIN(x, y) ((x) < (y) ? (x) : (y))
130 #endif
131 #define CLAMP(v, _min, _max) MAX((_min), MIN((_max), (v)))
132 #define CLAMP_OPPOSITE(v, _min, _max)                                         \
133 	((v) > (_max) ? (_min) : ((v) < (_min) ? (_max) : (v)))
134 #define SIGN(x) ((x) != 0 ? (x) / abs(x) : 1)
135 #define SQUARED(x) ((x) * (x))
136 #define SWAP(x, y, T)                                                         \
137 	do                                                                        \
138 	{                                                                         \
139 		T _tmp = x;                                                           \
140 		x = y;                                                                \
141 		y = _tmp;                                                             \
142 	} while (0)
143 
144 const char *StrGetFileExt(const char *filename);
145 
146 void PathGetDirname(char *buf, const char *path);
147 // Given /path/to/file, return file
148 const char *PathGetBasename(const char *path);
149 void PathGetWithoutExtension(char *buf, const char *path);
150 void PathGetBasenameWithoutExtension(char *buf, const char *path);
151 void RealPath(const char *src, char *dest);
152 void RelPath(char *buf, const char *to, const char *from);
153 void FixPathSeparator(char *dst, const char *src);
154 char *CDogsGetCWD(char *buf);
155 void RelPathFromCWD(char *buf, const char *to);
156 void GetDataFilePath(char *buf, const char *path);
157 
158 double Round(double x);
159 
160 double ToDegrees(double radians);
161 
162 struct vec2 CalcClosestPointOnLineSegmentToPoint(
163 	const struct vec2 l1, const struct vec2 l2, const struct vec2 p);
164 
165 typedef enum
166 {
167 	INPUT_DEVICE_UNSET,
168 	INPUT_DEVICE_KEYBOARD,
169 	INPUT_DEVICE_MOUSE,
170 	INPUT_DEVICE_JOYSTICK,
171 
172 	// Fake device used for co-op AI
173 	INPUT_DEVICE_AI,
174 
175 	INPUT_DEVICE_COUNT
176 } input_device_e;
177 
178 const char *InputDeviceName(const int d, const int deviceIndex);
179 
180 typedef enum
181 {
182 	ALLYCOLLISION_NORMAL,
183 	ALLYCOLLISION_REPEL,
184 	ALLYCOLLISION_NONE
185 } AllyCollision;
186 const char *AllyCollisionStr(int a);
187 int StrAllyCollision(const char *str);
188 
189 char *IntStr(int i);
190 char *PercentStr(int p);
191 char *Div8Str(int i);
192 void CamelToTitle(char *buf, const char *src);
193 bool StrEndsWith(const char *str, const char *suffix);
194 int Stricmp(const char *a, const char *b);
195 int CompareIntsAsc(const void *v1, const void *v2);
196 int CompareIntsDesc(const void *v1, const void *v2);
197 bool IntsEqual(const void *v1, const void *v2);
198 
199 // Helper macros for defining type/str conversion funcs
200 #define T2S(_type, _str)                                                      \
201 	case _type:                                                               \
202 		return _str;
203 #define S2T(_type, _str)                                                      \
204 	if (strcmp(s, _str) == 0)                                                 \
205 	{                                                                         \
206 		return _type;                                                         \
207 	}
208 
209 #define RAND_INT(_low, _high)                                                 \
210 	((_low) == (_high) ? (_low) : (_low) + (rand() % ((_high) - (_low))))
211 #define RAND_FLOAT(_low, _high)                                               \
212 	((_low) + ((float)rand() / RAND_MAX * ((_high) - (_low))))
213 #define RAND_DOUBLE(_low, _high)                                              \
214 	((_low) + ((double)rand() / RAND_MAX * ((_high) - (_low))))
215 #define RAND_BOOL() (RAND_INT(0, 1) == 0)
216 
217 typedef enum
218 {
219 	BODY_PART_HEAD,
220 	BODY_PART_HAIR,
221 	BODY_PART_BODY,
222 	BODY_PART_LEGS,
223 	BODY_PART_GUN_R,
224 	BODY_PART_GUN_L,
225 	BODY_PART_COUNT
226 } BodyPart;
227 
228 BodyPart StrBodyPart(const char *s);
229 
230 typedef enum
231 {
232 	PLACEMENT_ACCESS_ANY,		// place anywhere
233 	PLACEMENT_ACCESS_LOCKED,	// place in locked rooms
234 	PLACEMENT_ACCESS_NOT_LOCKED // don't place in locked rooms
235 } PlacementAccessFlags;
236 
237 int Pulse256(const int t);
238