1 //Copyright Paul Reiche, Fred Ford. 1992-2002
2 
3 /*
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 #ifndef UQM_UNITS_H_
20 #define UQM_UNITS_H_
21 
22 #include "libs/gfxlib.h"
23 
24 #if defined(__cplusplus)
25 extern "C" {
26 #endif
27 
28 extern int ScreenWidth;
29 extern int ScreenHeight;
30 
31 #define SCREEN_WIDTH ScreenWidth
32 #define SCREEN_HEIGHT ScreenHeight
33 #define SAFE_X 0
34 		/* Left and right screen margin to be left unused */
35 #define SAFE_Y 0
36 		/* Top and bottom screen margin to be left unused */
37 #define SIS_ORG_X (7 + SAFE_X)
38 #define SIS_ORG_Y (10 + SAFE_Y)
39 #define STATUS_WIDTH 64
40 		/* Width of the status "window" (the right part of the screen) */
41 #define STATUS_HEIGHT (SCREEN_HEIGHT - (SAFE_Y * 2))
42 		/* Height of the status "window" (the right part of the screen) */
43 #define SPACE_WIDTH (SCREEN_WIDTH - STATUS_WIDTH - (SAFE_X * 2))
44 		/* Width of the space "window" (the left part of the screen) */
45 #define SPACE_HEIGHT (SCREEN_HEIGHT - (SAFE_Y * 2))
46 		/* Height of the space "window" (the left part of the screen) */
47 #define SIS_SCREEN_WIDTH (SPACE_WIDTH - 14)
48 		/* Width of the usable part of the space "window" */
49 #define SIS_SCREEN_HEIGHT (SPACE_HEIGHT - 13)
50 		/* Height of the usable part of the space "window" */
51 #define RADAR_X (4 + (SCREEN_WIDTH - STATUS_WIDTH - SAFE_X))
52 #define RADAR_WIDTH (STATUS_WIDTH - 8)
53 #define RADAR_HEIGHT 53
54 #define RADAR_Y (SIS_ORG_Y + SIS_SCREEN_HEIGHT - RADAR_HEIGHT)
55 
56 #define SIS_TITLE_BOX_WIDTH    57
57 #define SIS_TITLE_WIDTH        (SIS_TITLE_BOX_WIDTH - 2)
58 #define SIS_TITLE_HEIGHT       8
59 #define SIS_SPACER_BOX_WIDTH   12
60 #define SIS_MESSAGE_BOX_WIDTH  (SIS_SCREEN_WIDTH - SIS_TITLE_BOX_WIDTH \
61 			- SIS_SPACER_BOX_WIDTH)
62 #define SIS_MESSAGE_WIDTH      (SIS_MESSAGE_BOX_WIDTH - 2)
63 #define SIS_MESSAGE_HEIGHT     SIS_TITLE_HEIGHT
64 
65 #define STATUS_MESSAGE_WIDTH   (STATUS_WIDTH - 4)
66 #define STATUS_MESSAGE_HEIGHT  7
67 
68 #define SHIP_NAME_WIDTH        (STATUS_WIDTH - 4)
69 #define SHIP_NAME_HEIGHT       7
70 
71 #define MAX_REDUCTION 3
72 #define MAX_VIS_REDUCTION 2
73 #define REDUCTION_SHIFT 1
74 #define NUM_VIEWS (MAX_VIS_REDUCTION + 1)
75 
76 #define ZOOM_SHIFT 8
77 #define MAX_ZOOM_OUT (1 << (ZOOM_SHIFT + MAX_REDUCTION - 1))
78 
79 #define ONE_SHIFT 2
80 #define BACKGROUND_SHIFT 3
81 #define SCALED_ONE (1 << ONE_SHIFT)
82 #define DISPLAY_TO_WORLD(x) ((x)<<ONE_SHIFT)
83 #define WORLD_TO_DISPLAY(x) ((x)>>ONE_SHIFT)
84 #define DISPLAY_ALIGN(x) ((COORD)(x)&~(SCALED_ONE-1))
85 #define DISPLAY_ALIGN_X(x) ((COORD)((COUNT)(x)%LOG_SPACE_WIDTH)&~(SCALED_ONE-1))
86 #define DISPLAY_ALIGN_Y(y) ((COORD)((COUNT)(y)%LOG_SPACE_HEIGHT)&~(SCALED_ONE-1))
87 
88 #define LOG_SPACE_WIDTH \
89 		(DISPLAY_TO_WORLD (SPACE_WIDTH) << MAX_REDUCTION)
90 #define LOG_SPACE_HEIGHT \
91 		(DISPLAY_TO_WORLD (SPACE_HEIGHT) << MAX_REDUCTION)
92 #define TRANSITION_WIDTH \
93 		(DISPLAY_TO_WORLD (SPACE_WIDTH) << MAX_VIS_REDUCTION)
94 #define TRANSITION_HEIGHT \
95 		(DISPLAY_TO_WORLD (SPACE_HEIGHT) << MAX_VIS_REDUCTION)
96 
97 #define MAX_X_UNIVERSE 9999
98 #define MAX_Y_UNIVERSE 9999
99 // Due to the added rounding error correction, the maximum logical X and Y
100 // in Hyperspace cannot go past 999.94999, otherwise the values will be
101 // rounded up to 1000.0. We do not want that so we subtract half a unit.
102 #define MAX_X_LOGICAL \
103 		(UNIVERSE_TO_LOGX (MAX_X_UNIVERSE + 1) - (UNIVERSE_TO_LOGX (1) >> 1) \
104 			- 1L)
105 // The Y axis is inverted with respect to the screen Y axis.
106 // (MAX_Y_UNIVERSE - 1) is really 1 for our purposes.
107 #define MAX_Y_LOGICAL \
108 		(UNIVERSE_TO_LOGY (-1) - (UNIVERSE_TO_LOGY (MAX_Y_UNIVERSE - 1) >> 1) \
109 			- 1L)
110 
111 #define SPHERE_RADIUS_INCREMENT 11
112 
113 #define MAX_FLEET_STRENGTH (254 * SPHERE_RADIUS_INCREMENT)
114 
115 // XXX: These corrected for the weird screen aspect ratio on DOS
116 //   In part because of them, hyperflight is slower vertically
117 #define UNIT_SCREEN_WIDTH 63
118 #define UNIT_SCREEN_HEIGHT 50
119 
120 // Bug #945: Simplified, these set the speed of SIS in Hyperspace and
121 //   Quasispace. The ratio between UNIVERSE_UNITS_ and LOG_UNITS_ is
122 //   what sets the speed, and it should be 1:16 to match the original.
123 //   The unit factors are reduced to keep the translation math within
124 //   32 bits. The original math is unnecessarily complex and depends
125 //   on the screen resolution when it should not.
126 //   Using the new math will break old savegames.
127 #ifdef NORMALIZED_HYPERSPACE_SPEED
128 #define LOG_UNITS_X      ((SDWORD)(UNIVERSE_UNITS_X * 16))
129 #define LOG_UNITS_Y      ((SDWORD)(UNIVERSE_UNITS_Y * 16))
130 #define UNIVERSE_UNITS_X (((MAX_X_UNIVERSE + 1) >> 4))
131 #define UNIVERSE_UNITS_Y (((MAX_Y_UNIVERSE + 1) >> 4))
132 #else
133 // Original (and now broken) Hyperspace speed factors
134 #define SECTOR_WIDTH 195
135 #define SECTOR_HEIGHT 25
136 
137 #define LOG_UNITS_X      ((SDWORD)(LOG_SPACE_WIDTH >> 4) * SECTOR_WIDTH)
138 #define LOG_UNITS_Y      ((SDWORD)(LOG_SPACE_HEIGHT >> 4) * SECTOR_HEIGHT)
139 #define UNIVERSE_UNITS_X (((MAX_X_UNIVERSE + 1) >> 4) * 10)
140 #define UNIVERSE_UNITS_Y (((MAX_Y_UNIVERSE + 1) >> 4))
141 #endif
142 
143 #define ROUNDING_ERROR(div)  ((div) >> 1)
144 
145 static inline COORD
logxToUniverse(SDWORD lx)146 logxToUniverse (SDWORD lx)
147 {
148 	return (COORD) ((lx * UNIVERSE_UNITS_X + ROUNDING_ERROR(LOG_UNITS_X))
149 			/ LOG_UNITS_X);
150 }
151 #define LOGX_TO_UNIVERSE(lx) \
152 		logxToUniverse (lx)
153 static inline COORD
logyToUniverse(SDWORD ly)154 logyToUniverse (SDWORD ly)
155 {
156 	return (COORD) (MAX_Y_UNIVERSE -
157 			((ly * UNIVERSE_UNITS_Y + ROUNDING_ERROR(LOG_UNITS_Y))
158 			/ LOG_UNITS_Y));
159 }
160 #define LOGY_TO_UNIVERSE(ly) \
161 		logyToUniverse (ly)
162 static inline SDWORD
universeToLogx(COORD ux)163 universeToLogx (COORD ux)
164 {
165 	return (ux * LOG_UNITS_X + ROUNDING_ERROR(UNIVERSE_UNITS_X))
166 			/ UNIVERSE_UNITS_X;
167 }
168 #define UNIVERSE_TO_LOGX(ux) \
169 		universeToLogx (ux)
170 static inline SDWORD
universeToLogy(COORD uy)171 universeToLogy (COORD uy)
172 {
173 	return ((MAX_Y_UNIVERSE - uy) * LOG_UNITS_Y
174 			+ ROUNDING_ERROR(UNIVERSE_UNITS_Y))
175 			/ UNIVERSE_UNITS_Y;
176 }
177 #define UNIVERSE_TO_LOGY(uy) \
178 		universeToLogy (uy)
179 
180 #define CIRCLE_SHIFT 6
181 #define FULL_CIRCLE (1 << CIRCLE_SHIFT)
182 #define OCTANT_SHIFT (CIRCLE_SHIFT - 3) /* (1 << 3) == 8 */
183 #define HALF_CIRCLE (FULL_CIRCLE >> 1)
184 #define QUADRANT (FULL_CIRCLE >> 2)
185 #define OCTANT (FULL_CIRCLE >> 3)
186 
187 #define FACING_SHIFT 4
188 
189 #define ANGLE_TO_FACING(a) (((a)+(1<<(CIRCLE_SHIFT-FACING_SHIFT-1))) \
190 										>>(CIRCLE_SHIFT-FACING_SHIFT))
191 #define FACING_TO_ANGLE(f) ((f)<<(CIRCLE_SHIFT-FACING_SHIFT))
192 
193 #define NORMALIZE_ANGLE(a) ((COUNT)((a)&(FULL_CIRCLE-1)))
194 #define NORMALIZE_FACING(f) ((COUNT)((f)&((1 << FACING_SHIFT)-1)))
195 
196 #define DEGREES_TO_ANGLE(d) NORMALIZE_ANGLE((((d) % 360) * FULL_CIRCLE \
197 				+ HALF_CIRCLE) / 360)
198 #define ANGLE_TO_DEGREES(d) (NORMALIZE_ANGLE(d) * 360 / FULL_CIRCLE)
199 
200 #define SIN_SHIFT 14
201 #define SIN_SCALE (1 << SIN_SHIFT)
202 #define INT_ADJUST(x) ((x)<<SIN_SHIFT)
203 #define FLT_ADJUST(x) (SIZE)((x)*SIN_SCALE)
204 #define UNADJUST(x) (SIZE)((x)>>SIN_SHIFT)
205 #define ROUND(x,y) ((x)+((x)>=0?((y)>>1):-((y)>>1)))
206 
207 extern SIZE sinetab[];
208 #define SINVAL(a) sinetab[NORMALIZE_ANGLE(a)]
209 #define COSVAL(a) SINVAL((a)+QUADRANT)
210 #define SINE(a,m) ((SIZE)((((long)SINVAL(a))*(long)(m))>>SIN_SHIFT))
211 #define COSINE(a,m) SINE((a)+QUADRANT,m)
212 extern COUNT ARCTAN (SIZE delta_x, SIZE delta_y);
213 
214 #define WRAP_VAL(v,w) ((COUNT)((v)<0?((v)+(w)):((v)>=(w)?((v)-(w)):(v))))
215 #define WRAP_X(x) WRAP_VAL(x,LOG_SPACE_WIDTH)
216 #define WRAP_Y(y) WRAP_VAL(y,LOG_SPACE_HEIGHT)
217 #define WRAP_DELTA_X(dx) ((dx)<0 ? \
218 				((-(dx)<=LOG_SPACE_WIDTH>>1)?(dx):(LOG_SPACE_WIDTH+(dx))) : \
219 				(((dx)<=LOG_SPACE_WIDTH>>1)?(dx):((dx)-LOG_SPACE_WIDTH)))
220 #define WRAP_DELTA_Y(dy) ((dy)<0 ? \
221 				((-(dy)<=LOG_SPACE_HEIGHT>>1)?(dy):(LOG_SPACE_HEIGHT+(dy))) : \
222 				(((dy)<=LOG_SPACE_HEIGHT>>1)?(dy):((dy)-LOG_SPACE_HEIGHT)))
223 #if defined(__cplusplus)
224 }
225 #endif
226 
227 #endif /* UQM_UNITS_H_ */
228