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_DISPLIST_H_
20 #define UQM_DISPLIST_H_
21 
22 #include <assert.h>
23 #include "port.h"
24 #include "libs/compiler.h"
25 #include "libs/memlib.h"
26 
27 #if defined(__cplusplus)
28 extern "C" {
29 #endif
30 
31 // Note that we MUST use the QUEUE_TABLE variant at this time, because
32 // certain gameplay elements depend on it. Namely, the maximum number
33 // of HyperSpace encounter globes chasing the player is defined by the
34 // allocated size of the encounter_q. If switched to non-table variant,
35 // the max number of encounters will be virtually unlimited the way the
36 // code works now.
37 #define QUEUE_TABLE
38 
39 typedef void* QUEUE_HANDLE;
40 
41 typedef UWORD OBJ_SIZE;
42 typedef QUEUE_HANDLE HLINK;
43 
44 typedef struct link
45 {
46 	// Every queue element of any queue must have these
47 	// two as the first members
48 	HLINK pred;
49 	HLINK succ;
50 } LINK;
51 
52 typedef struct /* queue */
53 {
54 	HLINK head;
55 	HLINK tail;
56 #ifdef QUEUE_TABLE
57 	BYTE  *pq_tab;
58 	HLINK free_list;
59 #endif
60 	COUNT object_size;
61 #ifdef QUEUE_TABLE
62 	BYTE num_objects;
63 #endif /* QUEUE_TABLE */
64 } QUEUE;
65 
66 #ifdef QUEUE_TABLE
67 
68 extern HLINK AllocLink (QUEUE *pq);
69 extern void FreeLink (QUEUE *pq, HLINK hLink);
70 
71 static inline LINK *
LockLink(const QUEUE * pq,HLINK h)72 LockLink (const QUEUE *pq, HLINK h)
73 {
74 	if (h) // Apparently, h==0 is OK
75 	{	// Make sure the link is actually in our queue!
76 		assert (pq->pq_tab && (BYTE*)h >= pq->pq_tab &&
77 				(BYTE*)h < pq->pq_tab + pq->object_size * pq->num_objects);
78 	}
79 	return (LINK*)h;
80 }
81 
82 static inline void
UnlockLink(const QUEUE * pq,HLINK h)83 UnlockLink (const QUEUE *pq, HLINK h)
84 {
85 	if (h) // Apparently, h==0 is OK
86 	{	// Make sure the link is actually in our queue!
87 		assert (pq->pq_tab && (BYTE*)h >= pq->pq_tab &&
88 				(BYTE*)h < pq->pq_tab + pq->object_size * pq->num_objects);
89 	}
90 }
91 
92 #define GetFreeList(pq) (pq)->free_list
93 #define SetFreeList(pq, h) (pq)->free_list = (h)
94 #define AllocQueueTab(pq,n) \
95 		((pq)->pq_tab = HMalloc (((COUNT)(pq)->object_size * \
96 		(COUNT)((pq)->num_objects = (BYTE)(n)))))
97 #define FreeQueueTab(pq) HFree ((pq)->pq_tab); (pq)->pq_tab = NULL
98 #define SizeQueueTab(pq) (COUNT)((pq)->num_objects)
99 #define GetLinkAddr(pq,i) (HLINK)((pq)->pq_tab + ((pq)->object_size * ((i) - 1)))
100 #else /* !QUEUE_TABLE */
101 #define AllocLink(pq)     (HLINK)HMalloc ((pq)->object_size)
102 #define LockLink(pq, h)   ((LINK*)(h))
103 #define UnlockLink(pq, h) ((void)(h))
104 #define FreeLink(pq,h)    HFree (h)
105 #endif /* QUEUE_TABLE */
106 
107 #define SetLinkSize(pq,s) ((pq)->object_size = (COUNT)(s))
108 #define GetLinkSize(pq) (COUNT)((pq)->object_size)
109 #define GetHeadLink(pq) ((pq)->head)
110 #define SetHeadLink(pq,h) ((pq)->head = (h))
111 #define GetTailLink(pq) ((pq)->tail)
112 #define SetTailLink(pq,h) ((pq)->tail = (h))
113 #define _GetPredLink(lpE) ((lpE)->pred)
114 #define _SetPredLink(lpE,h) ((lpE)->pred = (h))
115 #define _GetSuccLink(lpE) ((lpE)->succ)
116 #define _SetSuccLink(lpE,h) ((lpE)->succ = (h))
117 
118 extern BOOLEAN InitQueue (QUEUE *pq, COUNT num_elements, OBJ_SIZE size);
119 extern BOOLEAN UninitQueue (QUEUE *pq);
120 extern void ReinitQueue (QUEUE *pq);
121 extern void PutQueue (QUEUE *pq, HLINK hLink);
122 extern void InsertQueue (QUEUE *pq, HLINK hLink, HLINK hRefLink);
123 extern void RemoveQueue (QUEUE *pq, HLINK hLink);
124 extern COUNT CountLinks (QUEUE *pq);
125 void ForAllLinks(QUEUE *pq, void (*callback)(LINK *, void *), void *arg);
126 
127 #if defined(__cplusplus)
128 }
129 #endif
130 
131 #endif /* UQM_DISPLIST_H_ */
132