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