1 //
2 // Copyright(C) 2005-2014 Simon Howard
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (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 //
15 // Dehacked "mapping" code
16 // Allows the fields in structures to be mapped out and accessed by
17 // name
18 //
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "doomtype.h"
25 #include "i_system.h"
26 #include "m_misc.h"
27 
28 #include "deh_mapping.h"
29 
GetMappingEntryByName(deh_context_t * context,deh_mapping_t * mapping,char * name)30 static deh_mapping_entry_t *GetMappingEntryByName(deh_context_t *context,
31                                                   deh_mapping_t *mapping,
32                                                   char *name)
33 {
34     int i;
35 
36     for (i=0; mapping->entries[i].name != NULL; ++i)
37     {
38         deh_mapping_entry_t *entry = &mapping->entries[i];
39 
40         if (!strcasecmp(entry->name, name))
41         {
42             if (entry->location == NULL)
43             {
44                 DEH_Warning(context, "Field '%s' is unsupported", name);
45                 return NULL;
46             }
47 
48             return entry;
49         }
50     }
51 
52     // Not found.
53 
54     DEH_Warning(context, "Field named '%s' not found", name);
55 
56     return NULL;
57 }
58 
59 //
60 // Get the location of the specified field in the specified structure.
61 //
62 
GetStructField(void * structptr,deh_mapping_t * mapping,deh_mapping_entry_t * entry)63 static void *GetStructField(void *structptr,
64                             deh_mapping_t *mapping,
65                             deh_mapping_entry_t *entry)
66 {
67     unsigned int offset;
68 
69     offset = (uint8_t *)entry->location - (uint8_t *)mapping->base;
70 
71     return (uint8_t *)structptr + offset;
72 }
73 
74 //
75 // Set the value of a particular field in a structure by name
76 //
77 
DEH_SetMapping(deh_context_t * context,deh_mapping_t * mapping,void * structptr,char * name,int value)78 boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
79                        void *structptr, char *name, int value)
80 {
81     deh_mapping_entry_t *entry;
82     void *location;
83 
84     entry = GetMappingEntryByName(context, mapping, name);
85 
86     if (entry == NULL)
87     {
88         return false;
89     }
90 
91     // Sanity check:
92 
93     if (entry->is_string)
94     {
95         DEH_Error(context, "Tried to set '%s' as integer (BUG)", name);
96         return false;
97     }
98 
99     location = GetStructField(structptr, mapping, entry);
100 
101     //       printf("Setting %p::%s to %i (%i bytes)\n",
102     //               structptr, name, value, entry->size);
103 
104     // Set field content based on its type:
105 
106     switch (entry->size)
107     {
108         case 1:
109             * ((uint8_t *) location) = value;
110             break;
111         case 2:
112             * ((uint16_t *) location) = value;
113             break;
114         case 4:
115             * ((uint32_t *) location) = value;
116             break;
117         default:
118             DEH_Error(context, "Unknown field type for '%s' (BUG)", name);
119             return false;
120     }
121 
122     return true;
123 }
124 
125 //
126 // Set the value of a string field in a structure by name
127 //
128 
DEH_SetStringMapping(deh_context_t * context,deh_mapping_t * mapping,void * structptr,char * name,char * value)129 boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping,
130                              void *structptr, char *name, char *value)
131 {
132     deh_mapping_entry_t *entry;
133     void *location;
134 
135     entry = GetMappingEntryByName(context, mapping, name);
136 
137     if (entry == NULL)
138     {
139         return false;
140     }
141 
142     // Sanity check:
143 
144     if (!entry->is_string)
145     {
146         DEH_Error(context, "Tried to set '%s' as string (BUG)", name);
147         return false;
148     }
149 
150     location = GetStructField(structptr, mapping, entry);
151 
152     // Copy value into field:
153 
154     M_StringCopy(location, value, entry->size);
155 
156     return true;
157 }
158 
DEH_StructSHA1Sum(sha1_context_t * context,deh_mapping_t * mapping,void * structptr)159 void DEH_StructSHA1Sum(sha1_context_t *context, deh_mapping_t *mapping,
160                        void *structptr)
161 {
162     int i;
163 
164     // Go through each mapping
165 
166     for (i=0; mapping->entries[i].name != NULL; ++i)
167     {
168         deh_mapping_entry_t *entry = &mapping->entries[i];
169         void *location;
170 
171         if (entry->location == NULL)
172         {
173             // Unsupported field
174 
175             continue;
176         }
177 
178         // Add in data for this field
179 
180         location = (uint8_t *)structptr + ((uint8_t *)entry->location - (uint8_t *)mapping->base);
181 
182         switch (entry->size)
183         {
184             case 1:
185                 SHA1_UpdateInt32(context, *((uint8_t *) location));
186                 break;
187             case 2:
188                 SHA1_UpdateInt32(context, *((uint16_t *) location));
189                 break;
190             case 4:
191                 SHA1_UpdateInt32(context, *((uint32_t *) location));
192                 break;
193             default:
194                 I_Error("Unknown dehacked mapping field type for '%s' (BUG)",
195                         entry->name);
196                 break;
197         }
198     }
199 }
200 
201