1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the AUTHORS
5 * file distributed with this source distribution.
6 *
7 * Additional copyright for this file:
8 * Copyright (C) 1999-2000 Revolution Software Ltd.
9 * This code is based on source code created by Revolution Software,
10 * used with permission.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 */
27
28 #include "engines/icb/p4.h"
29 #include "engines/icb/common/px_globalvariables.h"
30
31 namespace ICB {
32
CpxGlobalScriptVariables()33 CpxGlobalScriptVariables::CpxGlobalScriptVariables() {
34 m_no_vars = 0;
35 m_sorted = 0;
36
37 int32 i;
38 for (i = 0; i < MAX_global_vars; i++) {
39 m_vars[i].hash = 666;
40 m_vars[i].value = 666;
41 m_varInit[i] = GLOBAL_VAR_NOT_SET;
42 }
43 }
44
FindVariable(uint32 hash)45 int32 CpxGlobalScriptVariables::FindVariable(uint32 hash) {
46 int32 index = -1;
47
48 if (m_sorted == 0) {
49 SortVariables();
50 } else {
51 // Use binary search system to find the variables
52 // The variables are stored in ascending hash sorted order
53 int32 min = 0;
54 int32 max = m_no_vars;
55 index = ((max - min) >> 1);
56 CpxVariable *pvar = m_vars + index;
57
58 // Start at the middle of the list
59 while (pvar->hash != hash) {
60 // Not found
61 if ((index == min) || (index == max)) {
62 index = -1;
63 break;
64 }
65
66 // Is it further up the table ?
67 if (hash > pvar->hash) {
68 min = index;
69 // Go down from min so we creep towards maximum
70 index = max - ((max - min) >> 1);
71 } else {
72 max = index;
73 // Go up from min so we creep towards minimum
74 index = min + ((max - min) >> 1);
75 }
76 pvar = m_vars + index;
77
78 if (max == min)
79 Fatal_error("GlobalVars Binary search failed max==min %d number %d", max, m_no_vars);
80 }
81
82 //#define CHECK_BINARY_SEARCH
83 #ifdef CHECK_BINARY_SEARCH
84 uint32 i;
85 int32 oldi = 0;
86 // Check the binarry search worked
87 for (i = 0; i < m_no_vars; i++) {
88 if (m_vars[i].hash == hash) {
89 oldi = i;
90 break;
91 }
92 }
93 if (oldi != index) {
94 Fatal_error("Binary search failed");
95 }
96 #endif
97 }
98
99 return index;
100 }
101
InitVariable(uint32 hash,int32 value,const char * name)102 void CpxGlobalScriptVariables::InitVariable(uint32 hash, int32 value, const char *name) {
103 // If the variable exists then it has already been initialised
104
105 int32 i = FindVariable(hash);
106 if (i == -1) {
107 m_vars[m_no_vars].hash = hash;
108 m_vars[m_no_vars].value = value;
109 if (name) {
110 Tdebug("gtable.txt", "%s , %d , 0x%X", name, value, hash);
111 }
112 m_no_vars++;
113 // The list is no int32er sorted !
114 m_sorted = 0;
115 } else {
116 // The variable has been set, so initing it is an error
117 // Fatal_error( "Global variable with hash 0x%08x has already been initialised",hash); // Game engine error
118 m_vars[i].value = value;
119 }
120 }
121
SetVariable(uint32 hash,int32 value)122 void CpxGlobalScriptVariables::SetVariable(uint32 hash, int32 value) {
123 // Set a variable
124 // You can't set a variable that has not been initialised
125 // Has the variable been defined already
126 int32 i = FindVariable(hash);
127 if (i != -1) {
128 // Once a variable is set then flag it as such
129 m_varInit[i] = GLOBAL_VAR_SET;
130
131 // Ok, just return the value
132 m_vars[i].value = value;
133 } else {
134 // The variable hasn't been set, so accessing it is an error
135 Fatal_error("SetVariable::Global variable with hash 0x%08x has been accessed before it was initialised", hash); // Game engine error
136 }
137 }
138
139 // warn = 1
140 // Give a warning if someone Get's the value before Setting it
141 // i.e. they are relying on the initialisation code which is bad
142 // warn = 0
143 // Don't give the warning - this is needed for save games which Get all global's !
GetVariable(uint32 hash,const char * name,int32 warn)144 int32 CpxGlobalScriptVariables::GetVariable(uint32 hash, const char *name, int32 warn) {
145 // Has the variable been defined already
146 int32 i = FindVariable(hash);
147 if (i != -1) {
148 if (warn == 1) {
149 // Give a warning if someone Get's the value before Setting it
150 // i.e. they are relying on the initialisation code which is bad
151 // Once a variable is set then flag it as such
152 if (m_varInit[i] == GLOBAL_VAR_NOT_SET) {
153 // Only give the warning once
154 m_varInit[i] = GLOBAL_VAR_SET;
155
156 if (name) {
157 { Message_box("GetVariable::Global variable '%s' hash 0x%08X value %d accessed before it was set", name, hash, m_vars[i].value); }
158 } else {
159 { Message_box("GetVariable::Global variable hash 0x%08X value %d accessed before it was set", hash, m_vars[i].value); }
160 }
161 }
162 }
163
164 // Ok, just return the value
165 return m_vars[i].value;
166 } else {
167 // The variable hasn't been set, so accessing it is an error
168 Fatal_error("GetVariable::Global variable with hash 0x%08X has been accessed before it was initialised", hash); // Game engine error
169 return 0;
170 }
171 }
172
173 //
174 // Sort the variables so searching for them is quicker !
175 // The search method can then use a binary chop system
176 //
SortVariables()177 void CpxGlobalScriptVariables::SortVariables() {
178 uint32 i;
179 uint32 j;
180 CpxVariable temp;
181 uint8 temp8;
182
183 // Sort the variable in ascending order
184 // e.g. lowest -> highest
185 for (i = 0; i < m_no_vars; i++) {
186 for (j = i + 1; j < m_no_vars; j++) {
187 if (m_vars[i].hash > m_vars[j].hash) {
188 temp = m_vars[i];
189 m_vars[i] = m_vars[j];
190 m_vars[j] = temp;
191
192 temp8 = m_varInit[i];
193 m_varInit[i] = m_varInit[j];
194 m_varInit[j] = temp8;
195 }
196 }
197 }
198 // The list is now sorted
199 m_sorted = 1;
200 }
201
202 } // End of namespace ICB
203