1 /*
2 * PROPRIETARY INFORMATION. This software is proprietary to POWDER
3 * Development, and is not to be reproduced, transmitted, or disclosed
4 * in any way without written permission.
5 *
6 * Produced by: Jeff Lait
7 *
8 * POWDER Development
9 *
10 * NAME: name.cpp ( POWDER Library, C++ )
11 *
12 * COMMENTS:
13 * This handles tracking the name library.
14 */
15
16 #include "mygba.h"
17 #include <stdio.h>
18 #include "sramstream.h"
19 #include "assert.h"
20 #include "name.h"
21 #include "msg.h"
22
23 #define INVALID_NAME 65535
24
25 int glb_numnames = 0;
26 char **glb_names = 0;
27 u8 *glb_namerefs = 0;
28
29 void
name_init(int numnames)30 name_init(int numnames)
31 {
32 int i;
33
34 for (i = 0; i < glb_numnames; i++)
35 {
36 if (glb_names[i])
37 free(glb_names[i]);
38 }
39 delete [] glb_names;
40 delete [] glb_namerefs;
41
42 if (numnames < 64)
43 numnames = 64;
44 glb_numnames = numnames;
45 glb_names = new char *[glb_numnames];
46 glb_namerefs = new u8[glb_numnames];
47 memset(glb_names, 0, sizeof(char *) * glb_numnames);
48 memset(glb_namerefs, 0, sizeof(u8) * glb_numnames);
49 }
50
51 int
name_alloc(const char * name)52 name_alloc(const char *name)
53 {
54 int i;
55
56 for (i = 0; i < glb_numnames; i++)
57 {
58 if (!glb_namerefs[i])
59 {
60 // Found a free name!
61 break;
62 }
63 }
64 if (i == glb_numnames)
65 {
66 // Need to realloc.
67 int newsize;
68 char **newnames;
69 u8 *newref;
70
71 newsize = glb_numnames * 2;
72 newnames = new char *[newsize];
73 newref = new u8[newsize];
74 memset(newnames, 0, sizeof(char *) * newsize);
75 memset(newref, 0, sizeof(u8) * newsize);
76
77 // Copy old ones.
78 memcpy(newnames, glb_names, sizeof(char *) * glb_numnames);
79 memcpy(newref, glb_namerefs, sizeof(u8) * glb_numnames);
80
81 // Delete & change over.
82 // Note that i is now a valid index.
83 glb_numnames = newsize;
84 delete [] glb_names;
85 glb_names = newnames;
86 delete [] glb_namerefs;
87 glb_namerefs = newref;
88 }
89
90 UT_ASSERT(glb_namerefs[i] == 0);
91
92 glb_namerefs[i] = 1;
93 glb_names[i] = strdup(name);
94 return i;
95 }
96
97 void
name_addref(int idx)98 name_addref(int idx)
99 {
100 if (idx < 0)
101 return;
102 if (idx == INVALID_NAME)
103 return;
104
105 if (idx >= glb_numnames)
106 {
107 UT_ASSERT(0);
108 return;
109 }
110 glb_namerefs[idx]++;
111 }
112
113 void
name_decref(int idx)114 name_decref(int idx)
115 {
116 if (idx < 0)
117 return;
118 if (idx == INVALID_NAME)
119 return;
120
121 if (idx >= glb_numnames)
122 {
123 UT_ASSERT(0);
124 return;
125 }
126 if (glb_namerefs[idx] == 0)
127 {
128 UT_ASSERT(0);
129 return;
130 }
131 glb_namerefs[idx]--;
132 if (!glb_namerefs[idx])
133 {
134 free(glb_names[idx]);
135 glb_names[idx] = 0;
136 }
137 }
138
139 void
name_load(SRAMSTREAM & is)140 name_load(SRAMSTREAM &is)
141 {
142 int i;
143 int numnames;
144 char buf[40];
145
146 is.uread(numnames, 16);
147
148 name_init(numnames);
149
150 for (i = 0; i < numnames; i++)
151 {
152 is.readString(buf, 30);
153 if (buf[0])
154 {
155 // This is a real string...
156 glb_names[i] = strdup(buf);
157 }
158 }
159 }
160
161 void
name_save(SRAMSTREAM & os)162 name_save(SRAMSTREAM &os)
163 {
164 int numnames, i;
165
166 // Count backward to find number of real names.
167 for (numnames = glb_numnames-1; numnames >= 0 && !glb_names[numnames];
168 numnames--);
169
170 // Include the last guy found.
171 numnames++;
172
173 os.write(numnames, 16);
174
175 for (i = 0; i < numnames; i++)
176 {
177 os.writeString(glb_names[i], 30);
178 }
179 }
180
181 //
182 // Now for the actual NAME definitions
183 //
184
NAME()185 NAME::NAME()
186 {
187 myIdx = INVALID_NAME;
188 }
189
~NAME()190 NAME::~NAME()
191 {
192 name_decref(myIdx);
193 }
194
NAME(const NAME & name)195 NAME::NAME(const NAME &name)
196 {
197 myIdx = name.myIdx;
198 name_addref(myIdx);
199 }
200
201 NAME &
operator =(const NAME & name)202 NAME::operator=(const NAME &name)
203 {
204 name_addref(name.myIdx);
205 name_decref(myIdx);
206 myIdx = name.myIdx;
207
208 return *this;
209 }
210
211 const char *
getName() const212 NAME::getName() const
213 {
214 if (myIdx == INVALID_NAME)
215 return 0;
216
217 if (myIdx >= glb_numnames)
218 {
219 UT_ASSERT(0);
220 return 0;
221 }
222
223 return glb_names[myIdx];
224 }
225
226 void
setName(const char * name)227 NAME::setName(const char *name)
228 {
229 name_decref(myIdx);
230 if (name && *name)
231 myIdx = name_alloc(name);
232 else
233 myIdx = INVALID_NAME;
234 }
235
236 void
save(SRAMSTREAM & os) const237 NAME::save(SRAMSTREAM &os) const
238 {
239 os.write(myIdx, 16);
240 }
241
242 void
load(SRAMSTREAM & is)243 NAME::load(SRAMSTREAM &is)
244 {
245 int val;
246
247 name_decref(myIdx);
248
249 is.uread(val, 16);
250
251 myIdx = val;
252 name_addref(myIdx);
253 }
254