1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: r_things.cpp 4469 2014-01-03 23:38:29Z dr_sean $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Copyright (C) 2006-2014 by The Odamex Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // DESCRIPTION:
20 //		Refresh of things, i.e. objects represented by sprites.
21 //
22 //-----------------------------------------------------------------------------
23 
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 
28 #include "m_alloc.h"
29 
30 #include "doomdef.h"
31 #include "m_swap.h"
32 #include "m_argv.h"
33 
34 #include "i_system.h"
35 #include "z_zone.h"
36 #include "w_wad.h"
37 
38 #include "r_local.h"
39 
40 #include "c_console.h"
41 #include "c_cvars.h"
42 #include "c_dispatch.h"
43 
44 #include "doomstat.h"
45 
46 #include "v_video.h"
47 
48 #include "cmdlib.h"
49 #include "s_sound.h"
50 
51 extern fixed_t FocalLengthX, FocalLengthY;
52 
53 
54 #define MINZ							(FRACUNIT*4)
55 #define BASEYCENTER 					(100)
56 
57 #define MAX_SPRITE_FRAMES 29		// [RH] Macro-ized as in BOOM.
58 #define SPRITE_NEEDS_INFO	MAXINT
59 
60 //
61 // INITIALIZATION FUNCTIONS
62 //
63 
64 // variables used to look up
65 //	and range check thing_t sprites patches
66 spritedef_t*	sprites;
67 int				numsprites;
68 
69 spriteframe_t	sprtemp[MAX_SPRITE_FRAMES];
70 int 			maxframe;
71 static const char*			spritename;
72 
R_CacheSprite(spritedef_t * sprite)73 void R_CacheSprite (spritedef_t *sprite)
74 {
75 	int i, r;
76 	patch_t *patch;
77 
78 	DPrintf ("cache sprite %s\n",
79 		sprite - sprites < NUMSPRITES ? sprnames[sprite - sprites] : "");
80 	for (i = 0; i < sprite->numframes; i++)
81 	{
82 		for (r = 0; r < 8; r++)
83 		{
84 			if (sprite->spriteframes[i].width[r] == SPRITE_NEEDS_INFO)
85 			{
86 				if (sprite->spriteframes[i].lump[r] == -1)
87 					I_Error ("Sprite %d, rotation %d has no lump", i, r);
88 				patch = W_CachePatch (sprite->spriteframes[i].lump[r]);
89 				sprite->spriteframes[i].width[r] = patch->width()<<FRACBITS;
90 				sprite->spriteframes[i].offset[r] = patch->leftoffset()<<FRACBITS;
91 				sprite->spriteframes[i].topoffset[r] = patch->topoffset()<<FRACBITS;
92 			}
93 		}
94 	}
95 }
96 
97 //
98 // R_InstallSpriteLump
99 // Local function for R_InitSprites.
100 //
101 // [RH] Removed checks for coexistance of rotation 0 with other
102 //		rotations and made it look more like BOOM's version.
103 //
R_InstallSpriteLump(int lump,unsigned frame,unsigned rotation,BOOL flipped)104 static void R_InstallSpriteLump (int lump, unsigned frame, unsigned rotation, BOOL flipped)
105 {
106 	if (frame >= MAX_SPRITE_FRAMES || rotation > 8)
107 		I_FatalError ("R_InstallSpriteLump: Bad frame characters in lump %i", lump);
108 
109 	if ((int)frame > maxframe)
110 		maxframe = frame;
111 
112 	if (rotation == 0)
113 	{
114 		// the lump should be used for all rotations
115         // false=0, true=1, but array initialised to -1
116         // allows doom to have a "no value set yet" boolean value!
117 		int r;
118 
119 		for (r = 7; r >= 0; r--)
120 			if (sprtemp[frame].lump[r] == -1)
121 			{
122 				sprtemp[frame].lump[r] = (short)(lump);
123 				sprtemp[frame].flip[r] = (byte)flipped;
124 				sprtemp[frame].rotate = false;
125 				sprtemp[frame].width[r] = SPRITE_NEEDS_INFO;
126 			}
127 	}
128 	else if (sprtemp[frame].lump[--rotation] == -1)
129 	{
130 		// the lump is only used for one rotation
131 		sprtemp[frame].lump[rotation] = (short)(lump);
132 		sprtemp[frame].flip[rotation] = (byte)flipped;
133 		sprtemp[frame].rotate = true;
134 		sprtemp[frame].width[rotation] = SPRITE_NEEDS_INFO;
135 	}
136 }
137 
138 
139 // [RH] Seperated out of R_InitSpriteDefs()
R_InstallSprite(const char * name,int num)140 static void R_InstallSprite (const char *name, int num)
141 {
142 	char sprname[5];
143 	int frame;
144 
145 	if (maxframe == -1)
146 	{
147 		sprites[num].numframes = 0;
148 		return;
149 	}
150 
151 	strncpy (sprname, name, 4);
152 	sprname[4] = 0;
153 
154 	maxframe++;
155 
156 	for (frame = 0 ; frame < maxframe ; frame++)
157 	{
158 		switch ((int)sprtemp[frame].rotate)
159 		{
160 		  case -1:
161 			// no rotations were found for that frame at all
162 			I_FatalError ("R_InstallSprite: No patches found for %s frame %c", sprname, frame+'A');
163 			break;
164 
165 		  case 0:
166 			// only the first rotation is needed
167 			break;
168 
169 		  case 1:
170 			// must have all 8 frames
171 			{
172 				int rotation;
173 
174 				for (rotation = 0; rotation < 8; rotation++)
175 					if (sprtemp[frame].lump[rotation] == -1)
176 						I_FatalError ("R_InstallSprite: Sprite %s frame %c is missing rotations",
177 									  sprname, frame+'A');
178 			}
179 			break;
180 		}
181 	}
182 
183 	// allocate space for the frames present and copy sprtemp to it
184 	sprites[num].numframes = maxframe;
185 	sprites[num].spriteframes = (spriteframe_t *)
186 		Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
187 	memcpy (sprites[num].spriteframes, sprtemp, maxframe * sizeof(spriteframe_t));
188 }
189 
190 
191 //
192 // R_InitSpriteDefs
193 // Pass a null terminated list of sprite names
194 //	(4 chars exactly) to be used.
195 // Builds the sprite rotation matrices to account
196 //	for horizontally flipped sprites.
197 // Will report an error if the lumps are inconsistant.
198 // Only called at startup.
199 //
200 // Sprite lump names are 4 characters for the actor,
201 //	a letter for the frame, and a number for the rotation.
202 // A sprite that is flippable will have an additional
203 //	letter/number appended.
204 // The rotation character can be 0 to signify no rotations.
205 //
R_InitSpriteDefs(const char ** namelist)206 void R_InitSpriteDefs (const char **namelist)
207 {
208 	// count the number of sprite names
209 	for (numsprites = 0; namelist[numsprites]; numsprites++)
210 		;
211 
212 	if (!numsprites)
213 		return;
214 
215 	sprites = (spritedef_t *)Z_Malloc(numsprites * sizeof(*sprites), PU_STATIC, NULL);
216 
217 	// scan all the lump names for each of the names,
218 	//	noting the highest frame letter.
219 	// Just compare 4 characters as ints
220 	for (int i = 0; i < numsprites; i++)
221 	{
222 		spritename = namelist[i];
223 		memset (sprtemp, -1, sizeof(sprtemp));
224 
225 		maxframe = -1;
226 		int intname = *(int *)namelist[i];
227 
228 		// scan the lumps,
229 		//	filling in the frames for whatever is found
230 		for (int l = lastspritelump; l >= firstspritelump; l--)
231 		{
232 			if (*(int *)lumpinfo[l].name == intname)
233 			{
234 				R_InstallSpriteLump (l,
235 									 lumpinfo[l].name[4] - 'A', // denis - fixme - security
236 									 lumpinfo[l].name[5] - '0',
237 									 false);
238 
239 				if (lumpinfo[l].name[6])
240 					R_InstallSpriteLump (l,
241 									 lumpinfo[l].name[6] - 'A',
242 									 lumpinfo[l].name[7] - '0',
243 									 true);
244 			}
245 		}
246 
247 		R_InstallSprite (namelist[i], i);
248 	}
249 }
250 
251 //
252 // GAME FUNCTIONS
253 //
254 int				MaxVisSprites;
255 vissprite_t 	*vissprites;
256 vissprite_t		*vissprite_p;
257 vissprite_t		*lastvissprite;
258 int 			newvissprite;
259 
260 
261 
262 //
263 // R_InitSprites
264 // Called at program start.
265 //
R_InitSprites(const char ** namelist)266 void R_InitSprites (const char **namelist)
267 {
268 	MaxVisSprites = 128;	// [RH] This is the initial default value. It grows as needed.
269 
270     M_Free(vissprites);
271 
272 	vissprites = (vissprite_t *)Malloc (MaxVisSprites * sizeof(vissprite_t));
273 	lastvissprite = &vissprites[MaxVisSprites];
274 
275 	R_InitSpriteDefs (namelist);
276 }
277 
278 VERSION_CONTROL (r_things_cpp, "$Id: r_things.cpp 4469 2014-01-03 23:38:29Z dr_sean $")
279 
280