Subversion Repositories Games.Carmageddon

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
20 pmbaty 1
#include "resource.h"
2
 
3
#include "CORE/FW/brlists.h"
4
#include "CORE/FW/diag.h"
5
#include "CORE/FW/fwsetup.h"
6
#include "CORE/FW/mem.h"
7
#include "CORE/FW/scratch.h"
8
#include "CORE/STD/brstdlib.h"
9
#include "harness/trace.h"
10
#include <stdio.h>
11
#include <stdlib.h>
12
 
13
#define RES_ALIGN 4
14
#define RESOURCE_SIZE(RES) ((RES)->size_h << 18)  | ((RES)->size_m << 10) | ((RES)->size_l << 2)
15
 
16
#define PANIC_ON_INVALID_RESOURCE_HEADER(RES_HDR)                                                        \
17
    do {                                                                                                 \
18
        if ((RES_HDR)->magic_num != 0xdeadbeef) {                                                        \
19
            LOG_PANIC("Bad resource header from user at %p. Was 0x%x", (RES_HDR), (RES_HDR)->magic_num); \
20
        }                                                                                                \
21
    } while (0)
22
 
23
// IDA: void* __usercall ResToUser@<EAX>(resource_header *r@<EAX>)
24
void* ResToUser(resource_header* r) {
25
    br_int_32 align;
26
    LOG_TRACE9("(%p)", r);
27
 
28
    align = fw.resource_class_index[r->class]->alignment;
29
    if (align <= 0) {
30
        align = RES_ALIGN;
31
    }
32
    return (void *) (((br_size_t)r + sizeof(resource_header) + align - 1) & ~(align - 1)); // Pierre-Marie Baty -- added type cast
33
}
34
 
35
// IDA: resource_header* __usercall UserToRes@<EAX>(void *r@<EAX>)
36
resource_header* UserToRes(void* r) {
37
    br_uint_8* p;
38
    LOG_TRACE9("(%p)", r);
39
 
40
    p = (br_uint_8*)r - 1;
41
    while (*p == 0) {
42
        p--;
43
    }
44
    return (resource_header*)(p - (sizeof(resource_header) - 1));
45
}
46
 
47
// IDA: void* __cdecl BrResAllocate(void *vparent, br_size_t size, br_uint_8 res_class)
48
void* BrResAllocate(void* vparent, br_size_t size, br_uint_8 res_class) {
49
    resource_header* res;
50
    resource_header* parent;
51
    br_int_32 malign;
52
    br_int_32 calign;
53
    br_int_32 pad;
54
    br_int_32 actual_pad;
55
    LOG_TRACE9("(%p, %d, %d)", vparent, size, res_class);
56
 
57
    size = (size + sizeof(resource_header) + RES_ALIGN - 1) & ~(RES_ALIGN - 1);
58
 
59
    malign = BrMemAlign(res_class);
60
 
61
    calign = fw.resource_class_index[res_class]->alignment;
62
    if (calign <= 0) {
63
        calign = RES_ALIGN;
64
    }
65
 
66
    pad = (~(malign - 1)) & (calign - 1);
67
    res = (resource_header*)BrMemAllocate(pad + size, res_class);
68
    actual_pad = ((((br_size_t)res + calign - 1) & (~(calign - 1))) - (br_size_t)res);
69
    if (actual_pad > pad) {
70
        BrFailure("Memory allocator broke alignment");
71
    }
72
    res->class = res_class;
73
    res->size_l = (br_uint_8) (size >> 2); // Pierre-Marie Baty -- added type cast
74
    res->size_m = (br_uint_8) (size >> 10); // Pierre-Marie Baty -- added type cast
75
    res->size_h = (br_uint_8) (size >> 18); // Pierre-Marie Baty -- added type cast
76
    BrSimpleNewList(&res->children);
77
    res->magic_num = 0xdeadbeef;
78
    res->magic_ptr = res;
79
 
80
    if (vparent != NULL) {
81
        // vparent points to a resource body, we track backwards to obtain its resource_header
82
        parent = UserToRes(vparent);
83
        PANIC_ON_INVALID_RESOURCE_HEADER(parent);
84
        BrSimpleAddHead(&parent->children, &res->node);
85
    }
86
 
87
    return ResToUser(res);
88
}
89
 
90
// IDA: void __usercall BrResInternalFree(resource_header *res@<EAX>, br_boolean callback@<EDX>)
91
void BrResInternalFree(resource_header* res, br_boolean callback) {
92
    //int c; // Pierre-Marie Baty -- unused variable
93
    void* r;
94
    LOG_TRACE10("(%p, %d)", res, callback);
95
 
96
    if (res->class == BR_MEMORY_FREE) {
97
        return;
98
    }
99
    if (callback != 0) {
100
        if (fw.resource_class_index[res->class]->free_cb != NULL) {
101
            fw.resource_class_index[res->class]->free_cb(ResToUser(res), res->class, RESOURCE_SIZE(res));
102
        }
103
    }
104
 
105
    while (res->children.head != NULL) {
106
        r = BrSimpleRemove(res->children.head);
107
        BrResInternalFree((resource_header*)r, 1);
108
    }
109
    if (res->node.prev != NULL) {
110
        BrSimpleRemove(&res->node);
111
    }
112
    res->magic_num = 1;
113
    res->magic_ptr = NULL;
114
    BrMemFree(res);
115
}
116
 
117
// IDA: void __cdecl BrResFree(void *vres)
118
void BrResFree(void* vres) {
119
    LOG_TRACE10("(%p)", vres);
120
 
121
    PANIC_ON_INVALID_RESOURCE_HEADER(UserToRes(vres));
122
    BrResInternalFree(UserToRes(vres), 1);
123
}
124
 
125
// IDA: void __cdecl BrResFreeNoCallback(void *vres)
126
void BrResFreeNoCallback(void* vres) {
127
    LOG_TRACE("(%p)", vres);
128
 
129
    PANIC_ON_INVALID_RESOURCE_HEADER(UserToRes(vres));
130
    BrResInternalFree(UserToRes(vres), 0);
131
}
132
 
133
// IDA: void* __cdecl BrResAdd(void *vparent, void *vres)
134
void* BrResAdd(void* vparent, void* vres) {
135
    resource_header* res;
136
    resource_header* parent;
137
    LOG_TRACE("(%p, %p)", vparent, vres);
138
 
139
    res = UserToRes(vres);
140
    parent = UserToRes(vparent);
141
 
142
    PANIC_ON_INVALID_RESOURCE_HEADER(res);
143
    PANIC_ON_INVALID_RESOURCE_HEADER(parent);
144
 
145
    if (res->node.prev != NULL) {
146
        BrSimpleRemove(&res->node);
147
    }
148
    BrSimpleAddHead(&parent->children, &res->node);
149
    return vres;
150
}
151
 
152
// IDA: void* __cdecl BrResRemove(void *vres)
153
void* BrResRemove(void* vres) {
154
    resource_header* res;
155
    LOG_TRACE("(%p)", vres);
156
 
157
    res = UserToRes(vres);
158
    PANIC_ON_INVALID_RESOURCE_HEADER(res);
159
 
160
    BrSimpleRemove(&res->node);
161
    return vres;
162
}
163
 
164
// IDA: br_uint_8 __cdecl BrResClass(void *vres)
165
br_uint_8 BrResClass(void* vres) {
166
    resource_header* res;
167
    LOG_TRACE("(%p)", vres);
168
 
169
    res = UserToRes(vres);
170
    PANIC_ON_INVALID_RESOURCE_HEADER(res);
171
    return res->class;
172
}
173
 
174
// IDA: br_boolean __cdecl BrResIsChild(void *vparent, void *vchild)
175
br_boolean BrResIsChild(void* vparent, void* vchild) {
176
    resource_header* parent;
177
    resource_header* child;
178
    resource_header* cp;
179
    LOG_TRACE("(%p, %p)", vparent, vchild);
180
 
181
    parent = UserToRes(vparent);
182
    child = UserToRes(vchild);
183
    PANIC_ON_INVALID_RESOURCE_HEADER(parent);
184
    PANIC_ON_INVALID_RESOURCE_HEADER(child);
185
 
186
    for (cp = (resource_header*)parent->children.head; cp != NULL; cp = (resource_header*)cp->node.next) {
187
        if (cp == child) {
188
            return 1;
189
        }
190
    }
191
    return 0;
192
}
193
 
194
// IDA: br_uint_32 __cdecl BrResSize(void *vres)
195
br_uint_32 BrResSize(void* vres) {
196
    resource_header* res;
197
    LOG_TRACE("(%p)", vres);
198
 
199
    res = UserToRes(vres);
200
    PANIC_ON_INVALID_RESOURCE_HEADER(res);
201
 
202
    return RESOURCE_SIZE(res);
203
}
204
 
205
// IDA: br_uint_32 __cdecl ResSizeTotal(void *vres, br_uint_32 *ptotal)
206
br_uint_32 ResSizeTotal(void* vres, br_uint_32* ptotal) {
207
    LOG_TRACE("(%p, %p)", vres, ptotal);
208
 
209
    *ptotal += BrResSize(vres);
210
    BrResChildEnum(vres, (br_resenum_cbfn*)ResSizeTotal, ptotal);
211
    return 0;
212
}
213
 
214
// IDA: br_uint_32 __cdecl BrResSizeTotal(void *vres)
215
br_uint_32 BrResSizeTotal(void* vres) {
216
    br_uint_32 total;
217
    LOG_TRACE("(%p)", vres);
218
 
219
    total = BrResSize(vres);
220
    BrResChildEnum(vres, (br_resenum_cbfn*)ResSizeTotal, &total);
221
    return total;
222
}
223
 
224
// IDA: br_uint_32 __cdecl BrResChildEnum(void *vres, br_resenum_cbfn *callback, void *arg)
225
br_uint_32 BrResChildEnum(void* vres, br_resenum_cbfn* callback, void* arg) {
226
    resource_header* res;
227
    resource_header* rp;
228
    br_uint_32 r;
229
    LOG_TRACE("(%p, %p, %p)", vres, callback, arg);
230
 
231
    res = UserToRes(vres);
232
    PANIC_ON_INVALID_RESOURCE_HEADER(res);
233
    r = 0;
234
    for (rp = (resource_header*)res->children.head; rp != NULL; rp = (resource_header*)rp->node.next) {
235
        r = callback(ResToUser(rp), arg);
236
        if (r != 0) {
237
            break;
238
        }
239
    }
240
    return r;
241
}
242
 
243
// IDA: br_uint_32 __cdecl BrResCheck(void *vres, int no_tag)
244
br_uint_32 BrResCheck(void* vres, int no_tag) {
245
    resource_header* res;
246
    LOG_TRACE("(%p, %d)", vres, no_tag);
247
 
248
    res = UserToRes(vres);
249
    // No PANIC_ON_INVALID_RESOURCE_HEADER check
250
 
251
    return res->magic_ptr == res && res->magic_num == 0xdeadbeef;
252
}
253
 
254
// IDA: char* __cdecl BrResStrDup(void *vparent, char *str)
255
char* BrResStrDup(void* vparent, char* str) {
256
    int l;
257
    char* nstr;
258
 
259
    l = BrStrLen(str);
260
    nstr = (char*)BrResAllocate(vparent, l + 1, BR_MEMORY_STRING);
261
    BrStrCpy(nstr, str);
262
    return nstr;
263
}
264
 
265
// IDA: void __usercall InternalResourceDump(resource_header *res@<EAX>, br_putline_cbfn *putline@<EDX>, void *arg@<EBX>, int level@<ECX>)
266
void InternalResourceDump(resource_header* res, br_putline_cbfn* putline, void* arg, int level) {
267
    int i;
268
    char* cp;
269
    resource_header* child;
270
    br_resource_class* rclass;
271
    LOG_TRACE9("(%p, %p, %p, %d)", res, putline, arg, level);
272
 
273
    rclass = fw.resource_class_index[res->class];
274
    cp = BrScratchString();
275
    for (i = 0; i < level; i++) {
276
        *cp = ' ';
277
        cp++;
278
    }
279
    sprintf(cp, "%p [%s] size=%u", res, rclass->identifier, RESOURCE_SIZE(res));
280
    putline(BrScratchString(), arg);
281
    for (child = (resource_header*)res->children.head; child != NULL; child = (resource_header*)child->node.next) {
282
        InternalResourceDump(child, putline, arg, level + 1);
283
    }
284
}
285
 
286
// IDA: void __cdecl BrResDump(void *vres, br_putline_cbfn *putline, void *arg)
287
void BrResDump(void* vres, br_putline_cbfn* putline, void* arg) {
288
    resource_header* res;
289
    LOG_TRACE("(%p, %p, %p)", vres, putline, arg);
290
 
291
    res = UserToRes(vres);
292
    PANIC_ON_INVALID_RESOURCE_HEADER(res);
293
    InternalResourceDump(res, putline, arg, 0);
294
}
295
 
296
// IDA: char* __cdecl BrResClassIdentifier(br_uint_8 res_class)
297
char* BrResClassIdentifier(br_uint_8 res_class) {
298
    br_resource_class* rclass;
299
    LOG_TRACE("(%d)", res_class);
300
 
301
    rclass = fw.resource_class_index[res_class];
302
    if (rclass == NULL) {
303
        return "<NULL>";
304
    }
305
    return rclass->identifier;
306
}