asar coverage - build #104


src/asar/
File: src/asar/interface-lib.cpp
Date: 2024-01-19 21:48:34
Lines:
252/274
92.0%
Functions:
29/30
96.7%
Branches:
153/272
56.2%

Line Branch Exec Source
1 #include "asar.h"
2 #include "crc32.h"
3 #include "virtualfile.h"
4 #include "platform/file-helpers.h"
5 #include "interface-shared.h"
6 #include "assembleblock.h"
7 #include "asar_math.h"
8 #include "platform/thread-helpers.h"
9
10 #if defined(CPPCLI)
11 #define EXPORT extern "C"
12 #elif defined(_WIN32)
13 #ifdef ASAR_SHARED
14 #define EXPORT extern "C" __declspec(dllexport)
15 #elif defined(ASAR_STATIC)
16 #define EXPORT extern "C"
17 #endif
18 #else
19 #define EXPORT extern "C" __attribute__ ((visibility ("default")))
20 #endif
21
22 static autoarray<const char *> prints;
23 static string symbolsfile;
24 static int numprint;
25 static uint32_t romCrc;
26
27 #define APIVERSION 400
28
29 // note: somewhat fragile, assumes that every patchparams struct inherits from exactly the previous one
30 /* $EXPORTSTRUCT_PP$
31 */
32 struct patchparams_base {
33 // The size of this struct. Set to (int)sizeof(patchparams).
34 int structsize;
35 };
36
37
38 /* $EXPORTSTRUCT$
39 */
40 struct stackentry {
41 const char * fullpath;
42 const char * prettypath;
43 int lineno;
44 const char * details;
45 };
46
47 /* $EXPORTSTRUCT$
48 */
49 struct errordata {
50 const char * fullerrdata;
51 const char * rawerrdata;
52 const char * block;
53 const char * filename;
54 int line;
55 const struct stackentry * callstack;
56 int callstacksize;
57 const char * errname;
58 };
59 static autoarray<errordata> errors;
60 static int numerror;
61
62 static autoarray<errordata> warnings;
63 static int numwarn;
64
65 /* $EXPORTSTRUCT$
66 */
67 struct labeldata {
68 const char * name;
69 int location;
70 };
71
72 /* $EXPORTSTRUCT$
73 */
74 struct definedata {
75 const char * name;
76 const char * contents;
77 };
78
79 /* $EXPORTSTRUCT$
80 */
81 struct warnsetting {
82 const char * warnid;
83 bool enabled;
84 };
85
86 /* $EXPORTSTRUCT$
87 */
88 struct memoryfile {
89 const char* path;
90 const void* buffer;
91 size_t length;
92 };
93
94 190 void print(const char * str)
95 {
96 190 prints[numprint++]= duplicate_string(str);
97 190 }
98
99 464 static void fillerror(errordata& myerr, const char* errname, const char * type, const char * str, bool show_block)
100 {
101
1/2
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
464 const char* current_filename = get_current_file_name();
102
2/2
✓ Branch 0 taken 463 times.
✓ Branch 1 taken 1 times.
464 if(current_filename) myerr.filename= duplicate_string(current_filename);
103 1 else myerr.filename = duplicate_string("");
104
1/2
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
464 myerr.line=get_current_line();
105
1/2
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
464 const char* current_block = get_current_block();
106
2/2
✓ Branch 0 taken 443 times.
✓ Branch 1 taken 21 times.
464 if (current_block) myerr.block= duplicate_string(current_block);
107 21 else myerr.block= duplicate_string("");
108 464 myerr.rawerrdata= duplicate_string(str);
109 234 string location;
110 234 string details;
111
1/2
✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
464 get_current_line_details(&location, &details);
112
6/12
✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 234 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 234 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 234 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 234 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 234 times.
✗ Branch 11 not taken.
694 myerr.fullerrdata= duplicate_string(location+": "+type+str+details+get_callstack());
113 464 myerr.errname = duplicate_string(errname);
114
115 234 autoarray<printable_callstack_entry> printable_stack;
116
1/2
✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
464 get_full_printable_callstack(&printable_stack, 0, false);
117
118 464 myerr.callstacksize = printable_stack.count;
119 464 myerr.callstack = static_cast<stackentry*>(malloc(sizeof(stackentry) * myerr.callstacksize));
120
121
2/2
✓ Branch 0 taken 15752 times.
✓ Branch 1 taken 464 times.
16216 for (int i = 0; i < myerr.callstacksize; ++i)
122 {
123 15752 stackentry& entry = const_cast<stackentry&>(myerr.callstack[i]);
124
125
1/2
✓ Branch 0 taken 5704 times.
✗ Branch 1 not taken.
15752 entry.fullpath = duplicate_string(printable_stack[i].fullpath);
126
1/2
✓ Branch 0 taken 5704 times.
✗ Branch 1 not taken.
15752 entry.prettypath = duplicate_string(printable_stack[i].prettypath);
127
1/2
✓ Branch 0 taken 5704 times.
✗ Branch 1 not taken.
15752 entry.lineno = printable_stack[i].lineno;
128
1/2
✓ Branch 0 taken 5704 times.
✗ Branch 1 not taken.
15752 entry.details = duplicate_string(printable_stack[i].details);
129 }
130 464 }
131
132 static bool ismath=false;
133 static string matherror;
134
135 963 void error_interface(int errid, int whichpass, const char * e_)
136 {
137 963 errored = true;
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 963 times.
963 if (ismath) matherror = e_;
139
2/2
✓ Branch 0 taken 398 times.
✓ Branch 1 taken 565 times.
963 else if (pass == whichpass) {
140 // don't show current block if the error came from an error command
141 398 bool show_block = (errid != error_id_error_command);
142
7/14
✓ Branch 0 taken 398 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 398 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 200 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 200 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 200 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 200 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 200 times.
✗ Branch 13 not taken.
596 fillerror(errors[numerror++], get_error_name((asar_error_id)errid), STR "error: (" + get_error_name((asar_error_id)errid) + "): ", e_, show_block);
143 }
144 else {}//ignore anything else
145 963 }
146
147 66 void warn(int errid, const char * str)
148 {
149 // don't show current block if the warning came from a warn command
150 66 bool show_block = (errid != warning_id_warn_command);
151
7/14
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 34 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 34 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 34 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 34 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 34 times.
✗ Branch 13 not taken.
98 fillerror(warnings[numwarn++], get_warning_name((asar_warning_id)errid), STR "warning: (" + get_warning_name((asar_warning_id)errid) + "): ", str, show_block);
152 66 }
153
154 static autoarray<labeldata> ldata;
155 static int labelsinldata = 0;
156 static autoarray<definedata> ddata;
157 static int definesinddata=0;
158
159 491 static void resetdllstuff()
160 {
161 #define free_and_null(x) free((void*)x); x = nullptr
162
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 491 times.
681 for (int i=0;i<numprint;i++)
163 {
164 190 free_and_null(prints[i]);
165 }
166 491 prints.reset();
167 491 numprint=0;
168
169
2/2
✓ Branch 0 taken 398 times.
✓ Branch 1 taken 491 times.
889 for (int i=0;i<numerror;i++)
170 {
171 398 free_and_null(errors[i].filename);
172 398 free_and_null(errors[i].rawerrdata);
173 398 free_and_null(errors[i].fullerrdata);
174 398 free_and_null(errors[i].block);
175 398 free_and_null(errors[i].errname);
176
177
2/2
✓ Branch 0 taken 15752 times.
✓ Branch 1 taken 398 times.
16348 for (int j=0;j<errors[i].callstacksize;++j)
178 {
179 15752 stackentry& entry = const_cast<stackentry&>(errors[i].callstack[j]);
180 15752 free_and_null(entry.fullpath);
181 15752 free_and_null(entry.prettypath);
182 15752 free_and_null(entry.details);
183 }
184 398 free_and_null(errors[i].callstack);
185 }
186 491 errors.reset();
187 491 numerror=0;
188
189
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 491 times.
557 for (int i=0;i<numwarn;i++)
190 {
191 66 free_and_null(warnings[i].filename);
192 66 free_and_null(warnings[i].rawerrdata);
193 66 free_and_null(warnings[i].fullerrdata);
194 66 free_and_null(warnings[i].block);
195 66 free_and_null(warnings[i].errname);
196
197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
98 for (int j=0;j<warnings[i].callstacksize;++j)
198 {
199 stackentry& entry = const_cast<stackentry&>(warnings[i].callstack[j]);
200 free_and_null(entry.fullpath);
201 free_and_null(entry.prettypath);
202 free_and_null(entry.details);
203 }
204 66 free_and_null(warnings[i].callstack);
205 }
206 491 warnings.reset();
207 491 numwarn=0;
208
209
2/2
✓ Branch 0 taken 2139 times.
✓ Branch 1 taken 491 times.
2630 for (int i=0;i<definesinddata;i++)
210 {
211 2139 free_and_null(ddata[i].name);
212 2139 free_and_null(ddata[i].contents);
213 }
214 491 ddata.reset();
215 491 definesinddata=0;
216
217
2/2
✓ Branch 0 taken 323 times.
✓ Branch 1 taken 491 times.
814 for (int i=0;i<labelsinldata;i++)
218 323 free((void*)ldata[i].name);
219 491 ldata.reset();
220 491 labelsinldata=0;
221 #undef free_and_null
222
223 491 romCrc = 0;
224 491 clidefines.reset();
225 491 reset_warnings_to_default();
226
227 491 reseteverything();
228 491 }
229
230 #define maxromsize (16*1024*1024)
231
232 static bool expectsNewAPI = false;
233
234 323 static void addlabel(const string & name, const snes_label & label_data)
235 {
236 labeldata label;
237 323 label.name = strdup(name);
238 323 label.location = (int)(label_data.pos & 0xFFFFFF);
239
1/2
✓ Branch 0 taken 164 times.
✗ Branch 1 not taken.
323 ldata[labelsinldata++] = label;
240 323 }
241
242 /* $EXPORTSTRUCT_PP$
243 */
244 struct patchparams_v200 : public patchparams_base
245 {
246 // Same parameters as asar_patch()
247 const char * patchloc;
248 char * romdata;
249 int buflen;
250 int * romlen;
251
252 // Include paths to use when searching files.
253 const char** includepaths;
254 int numincludepaths;
255
256 // A list of additional defines to make available to the patch.
257 const struct definedata* additional_defines;
258 int additional_define_count;
259
260 // Path to a text file to parse standard include search paths from.
261 // Set to NULL to not use any standard includes search paths.
262 const char* stdincludesfile;
263
264 // Path to a text file to parse standard defines from.
265 // Set to NULL to not use any standard defines.
266 const char* stddefinesfile;
267
268 // A list of warnings to enable or disable.
269 // Specify warnings in the format "WXXXX" where XXXX = warning ID.
270 const struct warnsetting * warning_settings;
271 int warning_setting_count;
272
273 // List of memory files to create on the virtual filesystem.
274 const struct memoryfile * memory_files;
275 int memory_file_count;
276
277 // Set override_checksum_gen to true and generate_checksum to true/false
278 // to force generating/not generating a checksum.
279 bool override_checksum_gen;
280 bool generate_checksum;
281
282 // Set this to true for generated error and warning texts to always
283 // contain their full call stack.
284 bool full_call_stack;
285 };
286
287 /* $EXPORTSTRUCT_PP$
288 */
289 struct patchparams : public patchparams_v200
290 {
291
292 };
293
294 486 static void asar_patch_begin(char * romdata_, int buflen, int * romlen_)
295 {
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (buflen != maxromsize)
297 {
298 romdata_r = (unsigned char*)malloc(maxromsize);
299 memcpy(const_cast<unsigned char*>(romdata_r)/*we just allocated this, it's safe to violate its const*/, romdata_, (size_t)*romlen_);
300 }
301 486 else romdata_r = (unsigned char*)romdata_;
302 486 romdata = (unsigned char*)malloc(maxromsize);
303 // RPG Hacker: Without this memset, freespace commands can (and probably will) fail.
304 486 memset((void*)romdata, 0, maxromsize);
305 486 memcpy(const_cast<unsigned char*>(romdata), romdata_, (size_t)*romlen_);
306 486 resetdllstuff();
307 486 romlen = *romlen_;
308 486 romlen_r = *romlen_;
309 486 }
310
311 486 static void asar_patch_main(const char * patchloc)
312 {
313
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 485 times.
486 if (!path_is_absolute(patchloc)) asar_throw_warning(pass, warning_id_relative_path_used, "patch file");
314
315 try
316 {
317
2/2
✓ Branch 0 taken 1418 times.
✓ Branch 1 taken 466 times.
1884 for (pass = 0;pass < 3;pass++)
318 {
319
1/2
✓ Branch 0 taken 1418 times.
✗ Branch 1 not taken.
1418 initstuff();
320
2/2
✓ Branch 0 taken 1398 times.
✓ Branch 1 taken 20 times.
1418 assemblefile(patchloc);
321 // RPG Hacker: Necessary, because finishpass() can throws warning and errors.
322
2/4
✓ Branch 0 taken 1398 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 729 times.
✗ Branch 3 not taken.
2067 callstack_push cs_push(callstack_entry_type::FILE, filesystem->create_absolute_path(nullptr, patchloc));
323
1/2
✓ Branch 0 taken 1398 times.
✗ Branch 1 not taken.
1398 finishpass();
324 1398 }
325 }
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 catch (errfatal&) {}
327 486 }
328
329 486 static bool asar_patch_end(char * romdata_, int buflen, int * romlen_)
330 {
331
2/2
✓ Branch 0 taken 244 times.
✓ Branch 1 taken 242 times.
486 if (checksum_fix_enabled) fixchecksum();
332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (romdata_ != (const char*)romdata_r) free(const_cast<unsigned char*>(romdata_r));
333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (buflen < romlen) asar_throw_error(pass, error_type_null, error_id_buffer_too_small);
334
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 345 times.
486 if (errored)
335 {
336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
141 if (numerror==0)
337 asar_throw_error(pass, error_type_null, error_id_phantom_error);
338 141 free(const_cast<unsigned char*>(romdata));
339 141 return false;
340 }
341
1/2
✓ Branch 0 taken 345 times.
✗ Branch 1 not taken.
345 if (*romlen_ != buflen)
342 {
343 345 *romlen_ = romlen;
344 }
345 345 romCrc = crc32((const uint8_t*)romdata, (size_t)romlen);
346 345 memcpy(romdata_, romdata, (size_t)romlen);
347 345 free(const_cast<unsigned char*>(romdata));
348 345 return true;
349 }
350
351 #if defined(__clang__)
352 # pragma clang diagnostic push
353 # pragma clang diagnostic ignored "-Wmissing-prototypes"
354 #endif
355
356 // this and asar_close are hardcoded in each api
357 5 EXPORT bool asar_init()
358 {
359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
5 if (!expectsNewAPI) return false;
360 3 return true;
361 }
362
363 /* $EXPORT$
364 * Returns the version, in the format major*10000+minor*100+bugfix*1. This
365 * means that 1.2.34 would be returned as 10234.
366 */
367 167 EXPORT int asar_version()
368 {
369 167 return get_version_int();
370 }
371
372 /* $EXPORT$
373 * Returns the API version, format major*100+minor. Minor is incremented on
374 * backwards compatible changes; major is incremented on incompatible changes.
375 * Does not have any correlation with the Asar version.
376 *
377 * It's not very useful directly, since asar_init() verifies this automatically.
378 * Calling this one also sets a flag that makes asar_init not instantly return
379 * false; this is so programs expecting an older API won't do anything unexpected.
380 */
381 9 EXPORT int asar_apiversion()
382 {
383 9 expectsNewAPI=true;
384 9 return APIVERSION;
385 }
386
387 /* $EXPORT$
388 * Clears out all errors, warnings and printed statements, and clears the file
389 * cache. Not really useful, since asar_patch() already does this.
390 */
391 EXPORT bool asar_reset()
392 {
393 resetdllstuff();
394 pass=0;
395 return true;
396 }
397
398 5 EXPORT void asar_close()
399 {
400 5 resetdllstuff();
401 5 }
402
403 /* $EXPORT$
404 * Applies a patch. The first argument is a filename (so Asar knows where to
405 * look for incsrc'd stuff); however, the ROM is in memory.
406 * This function assumes there are no headers anywhere, neither in romdata nor
407 * the sizes. romlen may be altered by this function; if this is undesirable,
408 * set romlen equal to buflen.
409 * The return value is whether any errors appeared (false=errors, call
410 * asar_geterrors for details). If there is an error, romdata and romlen will
411 * be left unchanged.
412 * See the documentation of struct patchparams for more information.
413 */
414 486 EXPORT bool asar_patch(const struct patchparams_base *params)
415 {
416 486 auto execute_patch = [&]() {
417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (params == nullptr)
418 {
419 asar_throw_error(pass, error_type_null, error_id_params_null);
420 }
421
422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486 times.
486 if (params->structsize != sizeof(patchparams_v200))
423 {
424 asar_throw_error(pass, error_type_null, error_id_params_invalid_size);
425 }
426
427 patchparams paramscurrent;
428 486 memset(&paramscurrent, 0, sizeof(paramscurrent));
429 486 memcpy(&paramscurrent, params, (size_t)params->structsize);
430
431
432
1/2
✓ Branch 0 taken 253 times.
✗ Branch 1 not taken.
486 asar_patch_begin(paramscurrent.romdata, paramscurrent.buflen, paramscurrent.romlen);
433
434 486 simple_callstacks = !paramscurrent.full_call_stack;
435
436 253 autoarray<string> includepaths;
437 253 autoarray<const char*> includepath_cstrs;
438
439
2/2
✓ Branch 0 taken 236 times.
✓ Branch 1 taken 486 times.
722 for (int i = 0; i < paramscurrent.numincludepaths; ++i)
440 {
441
2/6
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 236 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
236 if (!path_is_absolute(paramscurrent.includepaths[i])) asar_throw_warning(pass, warning_id_relative_path_used, "include search");
442
2/4
✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 118 times.
✗ Branch 3 not taken.
236 string& newpath = includepaths.append(paramscurrent.includepaths[i]);
443
1/2
✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
236 includepath_cstrs.append((const char*)newpath);
444 }
445
446
2/2
✓ Branch 0 taken 237 times.
✓ Branch 1 taken 249 times.
486 if (paramscurrent.stdincludesfile != nullptr) {
447
2/6
✓ Branch 0 taken 237 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 237 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
237 if (!path_is_absolute(paramscurrent.stdincludesfile)) asar_throw_warning(pass, warning_id_relative_path_used, "std includes file");
448
1/2
✓ Branch 0 taken 119 times.
✗ Branch 1 not taken.
119 string stdincludespath = paramscurrent.stdincludesfile;
449
1/2
✓ Branch 0 taken 237 times.
✗ Branch 1 not taken.
237 parse_std_includes(stdincludespath, includepaths);
450 237 }
451
452
2/2
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 486 times.
961 for (int i = 0; i < includepaths.count; ++i)
453 {
454
2/4
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 239 times.
✗ Branch 3 not taken.
475 includepath_cstrs.append((const char*)includepaths[i]);
455 }
456
457 486 size_t includepath_count = (size_t)includepath_cstrs.count;
458
1/2
✓ Branch 0 taken 253 times.
✗ Branch 1 not taken.
253 virtual_filesystem new_filesystem;
459
2/4
✓ Branch 0 taken 486 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 253 times.
✗ Branch 3 not taken.
486 new_filesystem.initialize(&includepath_cstrs[0], includepath_count);
460 486 filesystem = &new_filesystem;
461
462
2/2
✓ Branch 0 taken 260 times.
✓ Branch 1 taken 486 times.
746 for(int i = 0; i < paramscurrent.memory_file_count; ++i) {
463 260 memoryfile f = paramscurrent.memory_files[i];
464
1/2
✓ Branch 0 taken 260 times.
✗ Branch 1 not taken.
260 filesystem->add_memory_file(f.path, f.buffer, f.length);
465 }
466
467 486 clidefines.reset();
468
2/2
✓ Branch 0 taken 946 times.
✓ Branch 1 taken 486 times.
1432 for (int i = 0; i < paramscurrent.additional_define_count; ++i)
469 {
470
2/4
✓ Branch 0 taken 946 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 474 times.
✗ Branch 3 not taken.
946 string name = (paramscurrent.additional_defines[i].name != nullptr ? paramscurrent.additional_defines[i].name : "");
471
1/2
✓ Branch 0 taken 474 times.
✗ Branch 1 not taken.
946 strip_whitespace(name);
472
1/2
✓ Branch 0 taken 474 times.
✗ Branch 1 not taken.
946 name.strip_prefix('!'); // remove leading ! if present
473
2/6
✓ Branch 0 taken 946 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 946 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
946 if (!validatedefinename(name)) asar_throw_error(pass, error_type_null, error_id_cmdl_define_invalid, "asar_patch_ex() additional defines", name.data());
474
3/4
✓ Branch 0 taken 474 times.
✓ Branch 1 taken 472 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 474 times.
946 if (clidefines.exists(name)) {
475 asar_throw_error(pass, error_type_null, error_id_cmdl_define_override, "asar_patch_ex() additional define", name.data());
476 return false;
477 }
478
3/4
✓ Branch 0 taken 710 times.
✓ Branch 1 taken 236 times.
✓ Branch 2 taken 474 times.
✗ Branch 3 not taken.
946 string contents = (paramscurrent.additional_defines[i].contents != nullptr ? paramscurrent.additional_defines[i].contents : "");
479
2/4
✓ Branch 0 taken 946 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 474 times.
✗ Branch 3 not taken.
946 clidefines.create(name) = contents;
480
1/2
✓ Branch 0 taken 474 times.
✗ Branch 1 not taken.
946 }
481
482
2/2
✓ Branch 0 taken 237 times.
✓ Branch 1 taken 249 times.
486 if (paramscurrent.stddefinesfile != nullptr) {
483
2/6
✓ Branch 0 taken 237 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 237 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
237 if (!path_is_absolute(paramscurrent.stddefinesfile)) asar_throw_warning(pass, warning_id_relative_path_used, "std defines file");
484
1/2
✓ Branch 0 taken 119 times.
✗ Branch 1 not taken.
119 string stddefinespath = paramscurrent.stddefinesfile;
485
1/2
✓ Branch 0 taken 237 times.
✗ Branch 1 not taken.
237 parse_std_defines(stddefinespath);
486 237 } else {
487
1/2
✓ Branch 0 taken 249 times.
✗ Branch 1 not taken.
249 parse_std_defines(nullptr); // needed to populate builtin defines
488 }
489
490
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 486 times.
488 for (int i = 0; i < paramscurrent.warning_setting_count; ++i)
491 {
492
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 asar_warning_id warnid = parse_warning_id_from_string(paramscurrent.warning_settings[i].warnid);
493
494
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (warnid != warning_id_end)
495 {
496
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 set_warning_enabled(warnid, paramscurrent.warning_settings[i].enabled);
497 }
498 else
499 {
500 asar_throw_error(pass, error_type_null, error_id_invalid_warning_id, paramscurrent.warning_settings[i].warnid, "asar_patch_ex() warning_settings");
501 }
502 }
503
504
2/2
✓ Branch 0 taken 230 times.
✓ Branch 1 taken 256 times.
486 if(paramscurrent.override_checksum_gen) {
505 230 checksum_fix_enabled = paramscurrent.generate_checksum;
506 230 force_checksum_fix = true;
507 }
508
509
1/2
✓ Branch 0 taken 486 times.
✗ Branch 1 not taken.
486 asar_patch_main(paramscurrent.patchloc);
510
511 // RPG Hacker: Required before the destroy() below,
512 // otherwise it will leak memory.
513
1/2
✓ Branch 0 taken 486 times.
✗ Branch 1 not taken.
486 closecachedfiles();
514
515
1/2
✓ Branch 0 taken 486 times.
✗ Branch 1 not taken.
486 new_filesystem.destroy();
516 486 filesystem = nullptr;
517
518
1/2
✓ Branch 0 taken 486 times.
✗ Branch 1 not taken.
486 return asar_patch_end(paramscurrent.romdata, paramscurrent.buflen, paramscurrent.romlen);
519 486 };
520 #if defined(RUN_VIA_FIBER)
521 233 return run_as_fiber(execute_patch);
522 #elif defined(RUN_VIA_THREAD)
523
1/2
✓ Branch 0 taken 253 times.
✗ Branch 1 not taken.
506 return run_as_thread(execute_patch);
524 #else
525 return execute_patch();
526 #endif
527 }
528
529 /* $EXPORT$
530 * Returns the maximum possible size of the output ROM from asar_patch().
531 * Giving this size to buflen guarantees you will not get any buffer too small
532 * errors; however, it is safe to give smaller buffers if you don't expect any
533 * ROMs larger than 4MB or something.
534 */
535 206 EXPORT int asar_maxromsize()
536 {
537 206 return maxromsize;
538 }
539
540 /* $EXPORT$
541 * Get a list of all errors.
542 * All pointers from these functions are valid only until the same function is
543 * called again, or until asar_patch, asar_reset or asar_close is called,
544 * whichever comes first. Copy the contents if you need it for a longer time.
545 */
546 483 EXPORT const struct errordata * asar_geterrors(int * count)
547 {
548 483 *count=numerror;
549 483 return errors;
550 }
551
552 /* $EXPORT$
553 * Get a list of all warnings.
554 */
555 483 EXPORT const struct errordata * asar_getwarnings(int * count)
556 {
557 483 *count=numwarn;
558 483 return warnings;
559 }
560
561 /* $EXPORT$
562 * Get a list of all printed data.
563 */
564 467 EXPORT const char * const * asar_getprints(int * count)
565 {
566 467 *count=numprint;
567 467 return prints;
568 }
569
570 /* $EXPORT$
571 * Get a list of all labels.
572 */
573 167 EXPORT const struct labeldata * asar_getalllabels(int * count)
574 {
575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
167 for (int i=0;i<labelsinldata;i++) free((void*)ldata[i].name);
576 167 labelsinldata=0;
577 167 labels.each(addlabel);
578 167 *count=labelsinldata;
579 167 return ldata;
580 }
581
582 /* $EXPORT$
583 * Get the ROM location of one label. -1 means "not found".
584 */
585 4 EXPORT int asar_getlabelval(const char * name)
586 {
587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!stricmp(name, ":$:opcodes:$:")) return numopcodes;//aaah, you found me
588 int i;
589 try {
590
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 i=(int)labelval(&name).pos;
591 }
592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 catch(errfatal&) { return -1; }
593
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (*name || i<0) return -1;
594 3 else return i&0xFFFFFF;
595 }
596
597 /* $EXPORT$
598 * Get the value of a define.
599 */
600 168 EXPORT const char * asar_getdefine(const char * name)
601 {
602
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 84 times.
168 if (!defines.exists(name)) return "";
603 3 return defines.find(name);
604 }
605
606 /* $EXPORT$
607 * Parses all defines in the parameter. Note that it may emit errors.
608 */
609 2 EXPORT const char * asar_resolvedefines(const char * data)
610 {
611
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
3 static string out;
612 try
613 {
614
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 resolvedefines(out, data);
615 }
616 catch(errfatal&){}
617 2 return out;
618 }
619
620 2139 static void adddef(const string& name, string& value)
621 {
622 definedata define;
623 2139 define.name= duplicate_string(name);
624 2139 define.contents= duplicate_string(value);
625
1/2
✓ Branch 0 taken 1078 times.
✗ Branch 1 not taken.
2139 ddata[definesinddata++]=define;
626 2139 }
627
628 /* $EXPORT$
629 * Gets the values and names of all defines.
630 */
631 169 EXPORT const struct definedata * asar_getalldefines(int * count)
632 {
633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 169 times.
169 for (int i=0;i<definesinddata;i++)
634 {
635 free((void*)ddata[i].name);
636 free((void*)ddata[i].contents);
637 }
638 169 definesinddata=0;
639 169 defines.each(adddef);
640 169 *count=definesinddata;
641 169 return ddata;
642 }
643
644 /* $EXPORT$
645 * Parses a string containing math. It automatically assumes global scope (no
646 * namespaces), and has access to all functions and labels from the last call
647 * to asar_patch. Remember to check error to see if it's successful (NULL) or
648 * if it failed (non-NULL, contains a descriptive string). It does not affect
649 * asar_geterrors.
650 */
651 166 EXPORT double asar_math(const char * math_, const char ** error)
652 {
653 83 ns="";
654 166 namespace_list.reset();
655 166 sublabels.reset();
656 166 errored=false;
657 166 ismath=true;
658 166 initmathcore();
659 83 double rval=0;
660 try
661 {
662
1/2
✓ Branch 0 taken 166 times.
✗ Branch 1 not taken.
166 rval=(double)math(math_);
663 }
664 catch(errfatal&)
665 {
666 *error=matherror;
667 }
668 166 ismath=false;
669 166 deinitmathcore();
670 166 return rval;
671 }
672
673 /* $EXPORT$
674 * Get a list of all the blocks written to the ROM by calls such as
675 * asar_patch().
676 */
677 167 EXPORT const struct writtenblockdata * asar_getwrittenblocks(int * count)
678 {
679 167 *count = writtenblocks.count;
680 167 return writtenblocks;
681 }
682
683 /* $EXPORT$
684 * Get the mapper currently used by Asar.
685 */
686 174 EXPORT enum mapper_t asar_getmapper()
687 {
688 174 return mapper;
689 }
690
691 /* $EXPORT$
692 * Generates the contents of a symbols file for in a specific format.
693 */
694 166 EXPORT const char * asar_getsymbolsfile(const char* type){
695
3/6
✓ Branch 0 taken 166 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 83 times.
✗ Branch 5 not taken.
166 symbolsfile = create_symbols_file(type, romCrc);
696 166 return symbolsfile;
697 }
698
699 #if defined(__clang__)
700 # pragma clang diagnostic pop
701 #endif
702