asar coverage - build #


src/asar/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
103 of 306, 0 excluded
33.7%
Functions:
2 of 9, 0 excluded
22.2%
Branches:
147 of 1358, 0 excluded
10.8%

interface-cli.cpp
Line Branch Exec Source
1 #include "asar.h"
2 #include "libcon.h"
3 #include "platform/file-helpers.h"
4 #include "virtualfile.h"
5 #include "interface-shared.h"
6 #include "assembleblock.h"
7 #include "asar_math.h"
8 #include "unicode.h"
9 #include "platform/thread-helpers.h"
10
11 #if defined(windows)
12 # define NOMINMAX
13 # include <windows.h>
14 # include <io.h>
15 # include <fcntl.h>
16 #endif
17
18 #ifdef TIMELIMIT
19 # if defined(linux)
20 # include <sys/resource.h>
21 # include <signal.h>
22 # elif defined(_WIN32)
23 //WARNING: The Windows equivalent of SIGXCPU, job limits, is very poorly suited for short-running
24 // tasks like this; it's only checked approximately every seven seconds on the machine I tested on,
25 // and it kills the process instantly once this happens. (Additionally, due to an implementation
26 // quirk, it'll bug up if you ask for anything above about seven minutes, so don't do that.)
27 # define NOMINMAX
28 # include <windows.h>
29 # else
30 # error Time limits not configured for this OS.
31 # endif
32 #endif
33
34 #if defined(linux)
35 # include <unistd.h>
36 #elif defined(_WIN32)
37 # include <windows.h>
38 # include <io.h>
39 #endif
40
41 void print(const char * str)
42 {
43 puts(str);
44 }
45
46 static FILE * errloc=stderr;
47 static int errnum=0;
48
49 namespace ansi_text_color {
50 enum e : int {
51 BRIGHT_RED,
52 BRIGHT_YELLOW,
53 };
54 }
55
56 #if defined(_WIN32)
57 static bool has_windows_screen_info = false;
58 static DWORD windows_screen_attributes = 0u;
59 #endif
60
61 static void set_text_color(FILE* output_loc, string* in_out_str, ansi_text_color::e color)
62 {
63 #if defined(linux)
64 if (isatty(fileno(output_loc)))
65 {
66 switch (color)
67 {
68 case ansi_text_color::BRIGHT_RED:
69 *in_out_str = STR "\u001b[31;1m" + *in_out_str;
70 break;
71 case ansi_text_color::BRIGHT_YELLOW:
72 *in_out_str = STR "\u001b[33;1m" + *in_out_str;
73 break;
74 }
75 }
76 #elif defined(_WIN32)
77 // Currently using SetConsoleTextAttribute() approach over an ASCII escape character
78 // approach because it makes the output text easier to parse. Unfortunately, this
79 // also currently makes this a Windows-only solution.
80 CONSOLE_SCREEN_BUFFER_INFO screenInfo;
81 HANDLE win_handle = (HANDLE)_get_osfhandle(fileno(output_loc));
82 if (GetConsoleScreenBufferInfo(win_handle, &screenInfo) == TRUE)
83 {
84 DWORD color = 0u;
85 switch (color)
86 {
87 case ansi_text_color::BRIGHT_RED:
88 color = FOREGROUND_RED;
89 break;
90 case ansi_text_color::BRIGHT_YELLOW:
91 color = FOREGROUND_RED | FOREGROUND_GREEN;
92 break;
93 }
94
95 windows_screen_attributes = screenInfo.wAttributes;
96 has_windows_screen_info = true;
97 SetConsoleTextAttribute(win_handle, (windows_screen_attributes & 0x00F0) | FOREGROUND_INTENSITY | color);
98 }
99 #endif
100 }
101
102 static void reset_text_color(FILE* output_loc, string* in_out_str)
103 {
104 #if defined(linux)
105 if (isatty(fileno(output_loc)))
106 {
107 *in_out_str = STR "\u001b[0m" + *in_out_str;
108 }
109 #elif defined(_WIN32)
110 if (has_windows_screen_info)
111 {
112 HANDLE win_handle = (HANDLE)_get_osfhandle(fileno(output_loc));
113 SetConsoleTextAttribute(win_handle, windows_screen_attributes);
114 }
115 #endif
116 }
117
118 static int max_num_errors = 20;
119
120 void error_interface(const char* errid, int whichpass, const char * e_)
121 {
122 errored = true;
123 if (pass == whichpass)
124 {
125 errnum++;
126 const char* current_block = get_current_block();
127 // don't show current block if the error came from an error command or limit reached
128 bool show_block = (current_block && (strcmp(errid, "Eerror_command") != 0 && strcmp(errid, "Elimit_reached") != 0));
129 bool show_stack = strcmp(errid, "Elimit_reached") != 0;
130 string location;
131 string details;
132 get_current_line_details(&location, &details, !show_block);
133 string error_string = (show_stack ? location : STR "") + "error: (" + errid + "): " + e_;
134 string details_string = (show_stack ? details + get_callstack() : "") + "\n";
135 set_text_color(errloc, &error_string, ansi_text_color::BRIGHT_RED);
136 fputs(error_string, errloc);
137 reset_text_color(errloc, &details_string);
138 fputs(details_string, errloc);
139 if (errnum == max_num_errors + 1) throw_err_fatal(pass, err_limit_reached, max_num_errors);
140 }
141 }
142
143 static bool werror=false;
144 static bool warned=false;
145
146 void warn(int errid, const char * e_)
147 {
148 const char* current_block = get_current_block();
149 const char* warnname = get_warning_name((asar_warning_id)errid);
150 // don't show current block if the warning came from a warn command
151 bool show_block = (current_block && (strcmp(warnname, "Wwarn_command") != 0));
152 string location;
153 string details;
154 get_current_line_details(&location, &details, !show_block);
155 string warning_string = location+"warning: (" + warnname + "): " + e_;
156 string details_string = details + get_callstack() + "\n";
157 set_text_color(errloc, &warning_string, ansi_text_color::BRIGHT_YELLOW);
158 fputs(warning_string, errloc);
159 reset_text_color(errloc, &details_string);
160 fputs(details_string, errloc);
161 warned=true;
162 }
163
164 #ifdef TIMELIMIT
165 #if defined(linux)
166 void onsigxcpu(int ignored)
167 {
168 error<errnull>(pass, "Time limit exceeded.");
169 exit(1);
170 }
171 #elif defined(_WIN32)
172 //null
173 #endif
174 #endif
175
176 3 int main(int argc, const char * argv[])
177 {
178 #ifdef TIMELIMIT
179 #if defined(linux)
180 rlimit lim;
181 lim.rlim_cur=TIMELIMIT;
182 lim.rlim_max=RLIM_INFINITY;
183 setrlimit(RLIMIT_CPU, &lim);
184 signal(SIGXCPU, onsigxcpu);
185 #elif defined(_WIN32)
186 HANDLE hjob=CreateJobObject(NULL, nullptr);
187 AssignProcessToJobObject(hjob, GetCurrentProcess());
188 JOBOBJECT_BASIC_LIMIT_INFORMATION jbli;
189 jbli.LimitFlags=JOB_OBJECT_LIMIT_PROCESS_TIME;
190 jbli.PerProcessUserTimeLimit.LowPart=10*1000*1000*TIMELIMIT;
191 jbli.PerProcessUserTimeLimit.HighPart=0;
192 SetInformationJobObject(hjob, JobObjectBasicLimitInformation, &jbli, sizeof(jbli));
193 #endif
194 #endif
195
196 #define pause(sev) do { if (pause>=pause_##sev) libcon_pause(); } while(0)
197
198 enum {
199 pause_no,
200 pause_err,
201 pause_warn,
202 pause_yes,
203 3 } pause=pause_no;
204
205 enum cmdlparam
206 {
207 cmdlparam_none,
208
209 cmdlparam_addincludepath,
210 cmdlparam_adddefine,
211
212 cmdlparam_count
213 };
214
215 #if defined(windows)
216 // RPG Hacker: MinGW compatibility hack.
217 # if !defined(_O_U16TEXT)
218 # define _O_U16TEXT 0x20000
219 # endif
220
221 _setmode(_fileno(stdin), _O_U16TEXT);
222 // RPG Hacker: These would currently break Asar, because we're using narrow print functions everywhere.
223 //_setmode(_fileno(stdout), _O_U16TEXT);
224 //_setmode(_fileno(stderr), _O_U16TEXT);
225
226 SetConsoleOutputCP(CP_UTF8);
227 SetConsoleCP(CP_UTF8);
228
229
230 // RPG Hacker: Full Unicode support on Windows requires using a wchar_t command line.
231 // This means we have to convert our arguments from UTF-16 to UTF-8 here.
232 LPWSTR * argv_w = CommandLineToArgvW(GetCommandLineW(), &argc);
233
234 autoarray<string> u8_argv_arr;
235 autoarray<const char *> raw_argv_arr;
236
237 for (int i = 0; i < argc; ++i)
238 {
239 if (!utf16_to_utf8(&u8_argv_arr[i], argv_w[i]))
240 {
241 throw_err_null(pass, err_cmdl_utf16_to_utf8_failed, "Command line arguments on Windows must be valid UTF-16.");
242 pause(err);
243 return 1;
244 }
245
246 raw_argv_arr[i] = u8_argv_arr[i];
247 }
248
249 argv = (const char**)raw_argv_arr;
250 #endif
251
252 try
253 {
254 3 romdata_r = nullptr;
255
12/42
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 3 times.
✓ Branch 7 → 8 taken 3 times.
✗ Branch 7 → 9 not taken.
✓ Branch 12 → 13 taken 3 times.
✗ Branch 12 → 723 not taken.
✓ Branch 18 → 19 taken 3 times.
✗ Branch 18 → 715 not taken.
✓ Branch 24 → 25 taken 3 times.
✗ Branch 24 → 707 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 25 → 27 not taken.
✓ Branch 28 → 29 taken 3 times.
✗ Branch 28 → 532 not taken.
✗ Branch 28 → 703 not taken.
✓ Branch 29 → 30 taken 3 times.
✗ Branch 29 → 701 not taken.
✓ Branch 30 → 31 taken 3 times.
✗ Branch 30 → 527 not taken.
✗ Branch 30 → 699 not taken.
✓ Branch 31 → 32 taken 3 times.
✗ Branch 31 → 697 not taken.
✓ Branch 32 → 33 taken 3 times.
✗ Branch 32 → 522 not taken.
✗ Branch 32 → 695 not taken.
✓ Branch 33 → 34 taken 3 times.
✗ Branch 33 → 693 not taken.
✓ Branch 34 → 35 taken 3 times.
✗ Branch 34 → 519 not taken.
✗ Branch 34 → 691 not taken.
✗ Branch 35 → 36 not taken.
✗ Branch 35 → 517 not taken.
✗ Branch 36 → 37 not taken.
✗ Branch 36 → 515 not taken.
✗ Branch 37 → 38 not taken.
✗ Branch 37 → 513 not taken.
✗ Branch 38 → 39 not taken.
✗ Branch 38 → 511 not taken.
✗ Branch 39 → 40 not taken.
✗ Branch 39 → 509 not taken.
✗ Branch 40 → 41 not taken.
✗ Branch 40 → 507 not taken.
9 string version=STR"Asar "+dec(asarver_maj)+"."+dec(asarver_min)+"."+dec(asarver_bug)+(asarver_beta?"pre":"")
256
1/4
✓ Branch 35 → 36 taken 3 times.
✗ Branch 35 → 689 not taken.
✗ Branch 41 → 42 not taken.
✗ Branch 41 → 505 not taken.
12 +", originally developed by Alcaro, maintained by Asar devs.\n"+
257
1/4
✓ Branch 36 → 37 taken 3 times.
✗ Branch 36 → 687 not taken.
✗ Branch 42 → 43 not taken.
✗ Branch 42 → 503 not taken.
6 "Source code: https://github.com/RPGHacker/asar\n";
258 3 const char * myname=argv[0];
259
3/8
✗ Branch 54 → 55 not taken.
✗ Branch 54 → 56 not taken.
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 3 times.
✓ Branch 62 → 63 taken 3 times.
✗ Branch 62 → 67 not taken.
✗ Branch 63 → 64 not taken.
✓ Branch 63 → 65 taken 3 times.
3 if (strrchr(myname, '/')) myname=strrchr(myname, '/')+1;
260 //char * dot=strrchr(myname, '.');
261 //if (dot) *dot='\0';
262 //if (dot) *dot='.';
263
1/4
✗ Branch 56 → 57 not taken.
✗ Branch 56 → 633 not taken.
✓ Branch 67 → 68 taken 3 times.
✗ Branch 67 → 857 not taken.
3 libcon_init(argc, argv,
264 "[options] asm_file [rom_file]\n\n"
265 "Supported options:\n\n"
266 " --version \n"
267 " Display version information.\n\n"
268 " -v, --verbose \n"
269 " Enable verbose mode.\n\n"
270 " --symbols=<none/wla/nocash>\n"
271 " Specifies the format of the symbols output file. (Default is none for no symbols file)\n\n"
272 " --symbols-path=<filename>\n"
273 " Override the default path to the symbols output file. The default is the ROM's base name with an\n"
274 " extension of '.sym'.\n\n"
275 " --no-title-check\n"
276 " Disable verifying ROM title. (Note that irresponsible use will likely corrupt your ROM)\n\n"
277 " --pause-mode=<never/on-error/on-warning/always>\n"
278 " Specify when Asar should pause the application. (Never, on error, on warning or always)\n\n"
279 " --fix-checksum=<on/off>\n"
280 " Override Asar's checksum generation, allowing you to manually enable/disable generating a checksum\n\n"
281 " -I<path> \n"
282 " --include <path> \n"
283 " Add an include search path to Asar.\n\n"
284 " -D<def>[=<val>] \n"
285 " --define <def>[=<val>]\n"
286 " Add a define (optionally with a value) to Asar.\n\n"
287 " -werror \n"
288 " Treat warnings as errors.\n\n"
289 " -w<name> \n"
290 " Enable a specific warning.\n\n"
291 " -wno<name> \n"
292 " Disable a specific warning.\n\n"
293 " --full-error-stack\n"
294 " Enables detailed call stack information for warnings and errors.\n\n"
295 " --error-limit=<N> \n"
296 " Stop after encountering this many errors, instead of the default 20\n\n"
297 );
298 3 ignoretitleerrors=false;
299 3 string par;
300
1/2
✗ Branch 70 → 71 not taken.
✓ Branch 70 → 72 taken 3 times.
3 bool verbose=libcon_interactive;
301
1/4
✗ Branch 58 → 59 not taken.
✗ Branch 58 → 631 not taken.
✓ Branch 73 → 74 taken 3 times.
✗ Branch 73 → 855 not taken.
3 string symbols="";
302
1/4
✗ Branch 59 → 60 not taken.
✗ Branch 59 → 629 not taken.
✓ Branch 75 → 76 taken 3 times.
✗ Branch 75 → 853 not taken.
3 string symfilename="";
303
304 3 autoarray<string> includepaths;
305 3 autoarray<const char*> includepath_cstrs;
306 // need to do this before option processing since the option parser already does set_warning_enabled
307
1/4
✗ Branch 62 → 63 not taken.
✗ Branch 62 → 623 not taken.
✓ Branch 80 → 81 taken 3 times.
✗ Branch 80 → 847 not taken.
3 reset_warnings_to_default();
308
309
4/12
✗ Branch 219 → 220 not taken.
✗ Branch 219 → 623 not taken.
✗ Branch 220 → 221 not taken.
✗ Branch 220 → 623 not taken.
✗ Branch 222 → 64 not taken.
✗ Branch 222 → 223 not taken.
✓ Branch 289 → 290 taken 6 times.
✗ Branch 289 → 847 not taken.
✓ Branch 290 → 291 taken 6 times.
✗ Branch 290 → 847 not taken.
✓ Branch 293 → 82 taken 3 times.
✓ Branch 293 → 294 taken 3 times.
6 while ((par=libcon_option()))
310 {
311 3 cmdlparam postprocess_param = cmdlparam_none;
312 3 const char* postprocess_arg = nullptr;
313
314 #define checkstartmatch(arg, stringliteral) (!strncmp(arg, stringliteral, strlen(stringliteral)))
315
316
1/4
✗ Branch 65 → 66 not taken.
✗ Branch 65 → 67 not taken.
✗ Branch 83 → 84 not taken.
✓ Branch 83 → 85 taken 3 times.
3 if (par=="--no-title-check") ignoretitleerrors=true;
317
3/12
✗ Branch 68 → 69 not taken.
✗ Branch 68 → 71 not taken.
✗ Branch 70 → 71 not taken.
✗ Branch 70 → 72 not taken.
✗ Branch 73 → 74 not taken.
✗ Branch 73 → 75 not taken.
✓ Branch 86 → 87 taken 3 times.
✗ Branch 86 → 89 not taken.
✗ Branch 88 → 89 not taken.
✓ Branch 88 → 90 taken 3 times.
✗ Branch 91 → 92 not taken.
✓ Branch 91 → 93 taken 3 times.
3 else if (par == "-v" || par=="--verbose") verbose=true;
318
2/6
✗ Branch 76 → 77 not taken.
✗ Branch 76 → 87 not taken.
✗ Branch 94 → 95 not taken.
✓ Branch 94 → 96 taken 3 times.
✗ Branch 96 → 97 not taken.
✓ Branch 96 → 107 taken 3 times.
3 else if (checkstartmatch(par, "--symbols="))
319 {
320 if (par == "--symbols=none") symbols = "";
321 else if (par=="--symbols=wla") symbols="wla";
322 else if (par=="--symbols=nocash") symbols="nocash";
323 else libcon_badusage();
324 }
325
2/6
✗ Branch 88 → 89 not taken.
✗ Branch 88 → 91 not taken.
✗ Branch 108 → 109 not taken.
✓ Branch 108 → 110 taken 3 times.
✗ Branch 110 → 111 not taken.
✓ Branch 110 → 114 taken 3 times.
3 else if (checkstartmatch(par, "--symbols-path=")) {
326 symfilename=((const char*)par) + strlen("--symbols-path=");
327 }
328
2/6
✗ Branch 92 → 93 not taken.
✗ Branch 92 → 96 not taken.
✗ Branch 115 → 116 not taken.
✓ Branch 115 → 117 taken 3 times.
✗ Branch 117 → 118 not taken.
✓ Branch 117 → 125 taken 3 times.
3 else if (checkstartmatch(par, "--error-limit="))
329 {
330 char* out;
331 long lim = strtol((const char*)par + strlen("--error-limit="), &out, 10);
332 max_num_errors = lim;
333 }
334
1/4
✗ Branch 97 → 98 not taken.
✗ Branch 97 → 101 not taken.
✗ Branch 126 → 127 not taken.
✓ Branch 126 → 132 taken 3 times.
3 else if (par=="--version")
335 {
336 puts(version);
337 return 0;
338 }
339
2/6
✗ Branch 102 → 103 not taken.
✗ Branch 102 → 116 not taken.
✗ Branch 133 → 134 not taken.
✓ Branch 133 → 135 taken 3 times.
✗ Branch 135 → 136 not taken.
✓ Branch 135 → 149 taken 3 times.
3 else if (checkstartmatch(par, "--pause-mode="))
340 {
341 if (par=="--pause-mode=never") pause=pause_no;
342 else if (par=="--pause-mode=on-error") pause=pause_err;
343 else if (par=="--pause-mode=on-warning") pause=pause_warn;
344 else if (par=="--pause-mode=always") pause=pause_yes;
345 else libcon_badusage();
346 }
347
2/6
✗ Branch 117 → 118 not taken.
✗ Branch 117 → 125 not taken.
✗ Branch 150 → 151 not taken.
✓ Branch 150 → 152 taken 3 times.
✗ Branch 152 → 153 not taken.
✓ Branch 152 → 160 taken 3 times.
3 else if(checkstartmatch(par, "--fix-checksum=")) {
348 if(par=="--fix-checksum=on") {
349 force_checksum_fix = true;
350 checksum_fix_enabled = true;
351 } else if(par=="--fix-checksum=off") {
352 force_checksum_fix = true;
353 checksum_fix_enabled = false;
354 } else libcon_badusage();
355 }
356
2/6
✗ Branch 126 → 127 not taken.
✗ Branch 126 → 129 not taken.
✗ Branch 161 → 162 not taken.
✓ Branch 161 → 163 taken 3 times.
✗ Branch 163 → 164 not taken.
✓ Branch 163 → 167 taken 3 times.
3 else if (checkstartmatch(par, "-I"))
357 {
358 postprocess_param = cmdlparam_addincludepath;
359 postprocess_arg = ((const char*)par) + strlen("-I");
360 }
361
3/6
✗ Branch 130 → 131 not taken.
✗ Branch 130 → 133 not taken.
✗ Branch 168 → 169 not taken.
✓ Branch 168 → 170 taken 3 times.
✓ Branch 170 → 171 taken 2 times.
✓ Branch 170 → 174 taken 1 time.
3 else if (checkstartmatch(par, "-D"))
362 {
363 2 postprocess_param = cmdlparam_adddefine;
364 2 postprocess_arg = ((const char*)par) + strlen("-D");
365 }
366
1/4
✗ Branch 134 → 135 not taken.
✗ Branch 134 → 138 not taken.
✗ Branch 175 → 176 not taken.
✓ Branch 175 → 179 taken 1 time.
1 else if (par == "--include")
367 {
368 postprocess_arg = libcon_option_value();
369 if (postprocess_arg != nullptr)
370 {
371 postprocess_param = cmdlparam_addincludepath;
372 }
373 }
374
1/4
✗ Branch 139 → 140 not taken.
✗ Branch 139 → 143 not taken.
✓ Branch 180 → 181 taken 1 time.
✗ Branch 180 → 184 not taken.
1 else if (par == "--define")
375 {
376
1/4
✗ Branch 140 → 141 not taken.
✗ Branch 140 → 623 not taken.
✓ Branch 181 → 182 taken 1 time.
✗ Branch 181 → 847 not taken.
1 postprocess_arg = libcon_option_value();
377
1/4
✗ Branch 141 → 142 not taken.
✗ Branch 141 → 161 not taken.
✓ Branch 182 → 183 taken 1 time.
✗ Branch 182 → 210 not taken.
1 if (postprocess_arg != nullptr)
378 {
379 1 postprocess_param = cmdlparam_adddefine;
380 }
381 }
382 else if (checkstartmatch(par, "-w"))
383 {
384 const char* w_param = ((const char*)par) + strlen("-w");
385
386 if (checkstartmatch(w_param, "error"))
387 {
388 werror = true;
389 }
390 else if (checkstartmatch(w_param, "no"))
391 {
392 const char* name_start = w_param + strlen("no");
393 asar_warning_id warnid = parse_warning_id_from_string(name_start);
394
395 if (warnid != warning_id_end)
396 {
397 set_warning_enabled(warnid, false);
398 }
399 else
400 {
401 throw_warning(pass, warn_invalid_warning_id, name_start, "-wno");
402 }
403 }
404 else
405 {
406 asar_warning_id warnid = parse_warning_id_from_string(w_param);
407
408 if (warnid != warning_id_end)
409 {
410 set_warning_enabled(warnid, true);
411 }
412 else
413 {
414 throw_warning(pass, warn_invalid_warning_id, w_param, "-w");
415 }
416 }
417
418 }
419 else if (par=="--full-error-stack") simple_callstacks=false;
420 else libcon_badusage();
421
422
1/4
✗ Branch 161 → 162 not taken.
✗ Branch 161 → 166 not taken.
✗ Branch 210 → 211 not taken.
✓ Branch 210 → 217 taken 3 times.
3 if (postprocess_param == cmdlparam_addincludepath)
423 {
424 includepaths.append(postprocess_arg);
425 }
426
1/4
✗ Branch 166 → 167 not taken.
✗ Branch 166 → 218 not taken.
✓ Branch 217 → 218 taken 3 times.
✗ Branch 217 → 288 not taken.
3 else if (postprocess_param == cmdlparam_adddefine)
427 {
428
3/6
✗ Branch 167 → 168 not taken.
✗ Branch 167 → 193 not taken.
✗ Branch 218 → 219 not taken.
✓ Branch 218 → 220 taken 3 times.
✓ Branch 220 → 221 taken 2 times.
✓ Branch 220 → 256 taken 1 time.
3 if (strchr(postprocess_arg, '=') != nullptr)
429 {
430 // argument contains value, not only name
431
1/2
✗ Branch 221 → 222 not taken.
✓ Branch 221 → 223 taken 2 times.
2 const char* eq_loc = strchr(postprocess_arg, '=');
432
1/4
✗ Branch 168 → 169 not taken.
✗ Branch 168 → 541 not taken.
✓ Branch 224 → 225 taken 2 times.
✗ Branch 224 → 737 not taken.
2 string name = string(postprocess_arg, (int)(eq_loc - postprocess_arg));
433
1/4
✗ Branch 169 → 170 not taken.
✗ Branch 169 → 539 not taken.
✓ Branch 225 → 226 taken 2 times.
✗ Branch 225 → 735 not taken.
2 strip_whitespace(name);
434
1/4
✗ Branch 170 → 171 not taken.
✗ Branch 170 → 539 not taken.
✓ Branch 226 → 227 taken 2 times.
✗ Branch 226 → 735 not taken.
2 name.strip_prefix('!'); // remove leading ! if present
435
436
2/12
✗ Branch 172 → 173 not taken.
✗ Branch 172 → 539 not taken.
✗ Branch 173 → 174 not taken.
✗ Branch 173 → 176 not taken.
✗ Branch 175 → 176 not taken.
✗ Branch 175 → 539 not taken.
✓ Branch 228 → 229 taken 2 times.
✗ Branch 228 → 735 not taken.
✗ Branch 229 → 230 not taken.
✓ Branch 229 → 232 taken 2 times.
✗ Branch 231 → 232 not taken.
✗ Branch 231 → 735 not taken.
2 if (!validatedefinename(name)) throw_err_null(pass, err_cmdl_define_invalid, "command line defines", name.data());
437
438
2/8
✗ Branch 177 → 178 not taken.
✗ Branch 177 → 539 not taken.
✗ Branch 178 → 179 not taken.
✗ Branch 178 → 184 not taken.
✓ Branch 234 → 235 taken 2 times.
✗ Branch 234 → 735 not taken.
✗ Branch 235 → 236 not taken.
✓ Branch 235 → 241 taken 2 times.
2 if (clidefines.exists(name)) {
439 throw_err_null(pass, err_cmdl_define_override, "Command line define", name.data());
440 pause(err);
441 return 1;
442 }
443
2/8
✗ Branch 185 → 186 not taken.
✗ Branch 185 → 539 not taken.
✗ Branch 186 → 187 not taken.
✗ Branch 186 → 539 not taken.
✓ Branch 244 → 245 taken 2 times.
✗ Branch 244 → 735 not taken.
✓ Branch 246 → 247 taken 2 times.
✗ Branch 246 → 735 not taken.
2 clidefines.create(name) = eq_loc + 1;
444
1/4
✗ Branch 189 → 190 not taken.
✗ Branch 189 → 192 not taken.
✓ Branch 249 → 250 taken 2 times.
✗ Branch 249 → 251 not taken.
2 }
445 else
446 {
447 // argument doesn't have a value, only name
448
1/4
✗ Branch 193 → 194 not taken.
✗ Branch 193 → 544 not taken.
✓ Branch 257 → 258 taken 1 time.
✗ Branch 257 → 741 not taken.
1 string name = postprocess_arg;
449
1/4
✗ Branch 194 → 195 not taken.
✗ Branch 194 → 542 not taken.
✓ Branch 258 → 259 taken 1 time.
✗ Branch 258 → 739 not taken.
1 strip_whitespace(name);
450
1/4
✗ Branch 195 → 196 not taken.
✗ Branch 195 → 542 not taken.
✓ Branch 259 → 260 taken 1 time.
✗ Branch 259 → 739 not taken.
1 name.strip_prefix('!'); // remove leading ! if present
451
452
2/12
✗ Branch 197 → 198 not taken.
✗ Branch 197 → 542 not taken.
✗ Branch 198 → 199 not taken.
✗ Branch 198 → 201 not taken.
✗ Branch 200 → 201 not taken.
✗ Branch 200 → 542 not taken.
✓ Branch 261 → 262 taken 1 time.
✗ Branch 261 → 739 not taken.
✗ Branch 262 → 263 not taken.
✓ Branch 262 → 265 taken 1 time.
✗ Branch 264 → 265 not taken.
✗ Branch 264 → 739 not taken.
1 if (!validatedefinename(name)) throw_err_null(pass, err_cmdl_define_invalid, "command line defines", name.data());
453
454
2/8
✗ Branch 202 → 203 not taken.
✗ Branch 202 → 542 not taken.
✗ Branch 203 → 204 not taken.
✗ Branch 203 → 209 not taken.
✓ Branch 267 → 268 taken 1 time.
✗ Branch 267 → 739 not taken.
✗ Branch 268 → 269 not taken.
✓ Branch 268 → 274 taken 1 time.
1 if (clidefines.exists(name)) {
455 throw_err_null(pass, err_cmdl_define_override, "Command line define", name.data());
456 pause(err);
457 return 1;
458 }
459
2/8
✗ Branch 210 → 211 not taken.
✗ Branch 210 → 542 not taken.
✗ Branch 211 → 212 not taken.
✗ Branch 211 → 542 not taken.
✓ Branch 276 → 277 taken 1 time.
✗ Branch 276 → 739 not taken.
✓ Branch 278 → 279 taken 1 time.
✗ Branch 278 → 739 not taken.
1 clidefines.create(name) = "";
460
1/4
✗ Branch 214 → 215 not taken.
✗ Branch 214 → 217 not taken.
✓ Branch 281 → 282 taken 1 time.
✗ Branch 281 → 283 not taken.
1 }
461 }
462 }
463
2/4
✗ Branch 223 → 224 not taken.
✗ Branch 223 → 226 not taken.
✓ Branch 294 → 295 taken 1 time.
✓ Branch 294 → 299 taken 2 times.
3 if (verbose)
464 {
465
2/6
✗ Branch 225 → 226 not taken.
✗ Branch 225 → 623 not taken.
✗ Branch 296 → 297 not taken.
✓ Branch 296 → 298 taken 1 time.
✓ Branch 298 → 299 taken 1 time.
✗ Branch 298 → 847 not taken.
1 puts(version);
466 }
467
2/8
✗ Branch 226 → 227 not taken.
✗ Branch 226 → 623 not taken.
✗ Branch 227 → 228 not taken.
✗ Branch 227 → 623 not taken.
✓ Branch 300 → 301 taken 3 times.
✗ Branch 300 → 847 not taken.
✓ Branch 301 → 302 taken 3 times.
✗ Branch 301 → 847 not taken.
3 string asmname=libcon_require_filename("Enter patch name:");
468
2/8
✗ Branch 228 → 229 not taken.
✗ Branch 228 → 621 not taken.
✗ Branch 229 → 230 not taken.
✗ Branch 229 → 621 not taken.
✓ Branch 303 → 304 taken 3 times.
✗ Branch 303 → 845 not taken.
✓ Branch 304 → 305 taken 3 times.
✗ Branch 304 → 845 not taken.
3 string romname=libcon_optional_filename("Enter ROM name:", nullptr);
469 //char * outname=libcon_optional_filename("Enter output ROM name:", nullptr);
470
1/4
✗ Branch 230 → 231 not taken.
✗ Branch 230 → 619 not taken.
✓ Branch 305 → 306 taken 3 times.
✗ Branch 305 → 843 not taken.
3 libcon_end();
471
3/22
✗ Branch 232 → 233 not taken.
✗ Branch 232 → 237 not taken.
✗ Branch 234 → 235 not taken.
✗ Branch 234 → 619 not taken.
✗ Branch 235 → 236 not taken.
✗ Branch 235 → 237 not taken.
✗ Branch 238 → 239 not taken.
✗ Branch 238 → 240 not taken.
✗ Branch 239 → 240 not taken.
✗ Branch 239 → 619 not taken.
✗ Branch 307 → 308 not taken.
✓ Branch 307 → 309 taken 3 times.
✗ Branch 309 → 310 not taken.
✓ Branch 309 → 314 taken 3 times.
✗ Branch 311 → 312 not taken.
✗ Branch 311 → 843 not taken.
✗ Branch 312 → 313 not taken.
✗ Branch 312 → 314 not taken.
✗ Branch 315 → 316 not taken.
✓ Branch 315 → 317 taken 3 times.
✗ Branch 316 → 317 not taken.
✗ Branch 316 → 843 not taken.
3 if (!strchr(asmname, '.') && !file_exists(asmname)) asmname+=".asm";
472
1/4
✗ Branch 241 → 242 not taken.
✗ Branch 241 → 268 not taken.
✗ Branch 318 → 319 not taken.
✓ Branch 318 → 358 taken 3 times.
3 if (!romname)
473 {
474 string romnametmp = get_base_name(asmname);
475 if (file_exists(romnametmp+".sfc")) romname=romnametmp+".sfc";
476 else if (file_exists(romnametmp+".smc")) romname=romnametmp+".smc";
477 else romname=romnametmp+".sfc";
478 }
479
3/18
✗ Branch 269 → 270 not taken.
✗ Branch 269 → 274 not taken.
✗ Branch 271 → 272 not taken.
✗ Branch 271 → 619 not taken.
✗ Branch 272 → 273 not taken.
✗ Branch 272 → 274 not taken.
✗ Branch 275 → 276 not taken.
✗ Branch 275 → 288 not taken.
✗ Branch 359 → 360 not taken.
✓ Branch 359 → 361 taken 3 times.
✗ Branch 361 → 362 not taken.
✓ Branch 361 → 366 taken 3 times.
✗ Branch 363 → 364 not taken.
✗ Branch 363 → 843 not taken.
✗ Branch 364 → 365 not taken.
✗ Branch 364 → 366 not taken.
✗ Branch 367 → 368 not taken.
✓ Branch 367 → 386 taken 3 times.
3 else if (!strchr(romname, '.') && !file_exists(romname))
480 {
481 if (file_exists(romname+".sfc")) romname+=".sfc";
482 else if (file_exists(romname+".smc")) romname+=".smc";
483 }
484
2/8
✗ Branch 289 → 290 not taken.
✗ Branch 289 → 619 not taken.
✗ Branch 290 → 291 not taken.
✗ Branch 290 → 298 not taken.
✓ Branch 387 → 388 taken 3 times.
✗ Branch 387 → 843 not taken.
✓ Branch 388 → 389 taken 3 times.
✗ Branch 388 → 396 not taken.
3 if (!file_exists(romname))
485 {
486
1/4
✗ Branch 292 → 293 not taken.
✗ Branch 292 → 619 not taken.
✓ Branch 390 → 391 taken 3 times.
✗ Branch 390 → 843 not taken.
3 FileHandleType f = open_file(romname, FileOpenMode_Write);
487
1/4
✗ Branch 293 → 294 not taken.
✗ Branch 293 → 297 not taken.
✗ Branch 391 → 392 not taken.
✓ Branch 391 → 395 taken 3 times.
3 if (f == InvalidFileHandle)
488 {
489 throw_err_fatal(pass, err_create_rom_failed);
490 }
491
1/4
✗ Branch 297 → 298 not taken.
✗ Branch 297 → 619 not taken.
✓ Branch 395 → 396 taken 3 times.
✗ Branch 395 → 843 not taken.
3 close_file(f);
492 }
493
2/8
✗ Branch 299 → 300 not taken.
✗ Branch 299 → 619 not taken.
✗ Branch 300 → 301 not taken.
✗ Branch 300 → 304 not taken.
✓ Branch 397 → 398 taken 3 times.
✗ Branch 397 → 843 not taken.
✗ Branch 398 → 399 not taken.
✓ Branch 398 → 402 taken 3 times.
3 if (!openrom(romname, false))
494 {
495 pause(err);
496 return 1;
497 }
498 //check if the ROM title and checksum looks sane
499
1/10
✗ Branch 304 → 305 not taken.
✗ Branch 304 → 357 not taken.
✗ Branch 305 → 306 not taken.
✗ Branch 305 → 357 not taken.
✗ Branch 402 → 403 not taken.
✓ Branch 402 → 481 taken 3 times.
✗ Branch 403 → 404 not taken.
✗ Branch 403 → 405 not taken.
✗ Branch 405 → 406 not taken.
✗ Branch 405 → 481 not taken.
3 if (romlen>=32768 && !ignoretitleerrors)
500 {
501 bool validtitle=setmapper();
502 if (!validtitle)
503 {
504 string title;
505 for (int i=0;i<21;i++)
506 {
507 unsigned char c=romdata[snestopc(0x00FFC0+i)];
508 if (c==7) c=14;
509 if (c==8) c=27;//to not generate more hard-to-print characters than needed
510 if (c==9) c=26;//random characters are picked in accordance with the charset Windows-1252, but they should be garbage in all charsets
511 if (c=='\r') c=17;
512 if (c=='\n') c=25;
513 if (c=='\0') c=155;
514 title+=(char)c;
515 }
516 if (libcon_interactive)
517 {
518 if (!libcon_question_bool(STR"Warning: The ROM title appears to be \""+title+"\", which looks like garbage. "
519 "Is this your ROM title? (Note that improperly answering \"yes\" will crash your ROM.)", false))
520 {
521 puts("Assembling aborted. snespurify should be able to fix your ROM.");
522 return 1;
523 }
524 }
525 else
526 {
527 puts(STR"Error: The ROM title appears to be \""+title+"\", which looks like garbage. "
528 "If this is the ROM title, add --no-title-check to the command line options. If the ROM title is something else, use snespurify on your ROM.");
529 pause(err);
530 return 1;
531 }
532 }
533 }
534
535
2/8
✗ Branch 357 → 358 not taken.
✗ Branch 357 → 586 not taken.
✗ Branch 358 → 359 not taken.
✗ Branch 358 → 584 not taken.
✓ Branch 484 → 485 taken 3 times.
✗ Branch 484 → 799 not taken.
✓ Branch 485 → 486 taken 3 times.
✗ Branch 485 → 797 not taken.
3 string stdincludespath = STR dir(argv[0]) + "stdincludes.txt";
536
1/4
✗ Branch 361 → 362 not taken.
✗ Branch 361 → 617 not taken.
✓ Branch 489 → 490 taken 3 times.
✗ Branch 489 → 841 not taken.
3 parse_std_includes(stdincludespath, includepaths);
537
538
1/4
✗ Branch 367 → 363 not taken.
✗ Branch 367 → 368 not taken.
✗ Branch 499 → 491 not taken.
✓ Branch 499 → 500 taken 3 times.
3 for (int i = 0; i < includepaths.count; ++i)
539 {
540 includepath_cstrs.append((const char*)includepaths[i]);
541 }
542
543 3 size_t includepath_count = (size_t)includepath_cstrs.count;
544
1/4
✗ Branch 368 → 369 not taken.
✗ Branch 368 → 617 not taken.
✓ Branch 501 → 502 taken 3 times.
✗ Branch 501 → 841 not taken.
3 virtual_filesystem new_filesystem;
545
2/8
✗ Branch 369 → 370 not taken.
✗ Branch 369 → 615 not taken.
✗ Branch 370 → 371 not taken.
✗ Branch 370 → 615 not taken.
✓ Branch 502 → 503 taken 3 times.
✗ Branch 502 → 839 not taken.
✓ Branch 503 → 504 taken 3 times.
✗ Branch 503 → 839 not taken.
3 new_filesystem.initialize(&includepath_cstrs[0], includepath_count);
546 3 filesystem = &new_filesystem;
547
548
2/8
✗ Branch 371 → 372 not taken.
✗ Branch 371 → 590 not taken.
✗ Branch 372 → 373 not taken.
✗ Branch 372 → 588 not taken.
✓ Branch 507 → 508 taken 3 times.
✗ Branch 507 → 805 not taken.
✓ Branch 508 → 509 taken 3 times.
✗ Branch 508 → 803 not taken.
3 string stddefinespath = STR dir(argv[0]) + "stddefines.txt";
549
1/4
✗ Branch 375 → 376 not taken.
✗ Branch 375 → 613 not taken.
✓ Branch 512 → 513 taken 3 times.
✗ Branch 512 → 837 not taken.
3 parse_std_defines(stddefinespath);
550
551 3 auto execute_patch = [&]()
552 {
553 try {
554
2/4
✗ Branch 14 → 3 not taken.
✗ Branch 14 → 15 not taken.
✓ Branch 22 → 3 taken 9 times.
✓ Branch 22 → 23 taken 3 times.
12 for (pass=0;pass<3;pass++)
555 {
556 //pass 1: find which bank all labels are in, for label optimizations
557 // freespaces are listed as above 0xFFFFFF, to find if it's in the ROM or if it's dynamic
558 //pass 2: find where exactly all labels are
559 //pass 3: assemble it all
560
1/3
✓ Branch 3 → 4 taken 9 times.
✗ Branch 3 → 21 not taken.
✗ Branch 3 → 29 not taken.
9 initstuff();
561
1/4
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 21 not taken.
✓ Branch 7 → 8 taken 9 times.
✗ Branch 7 → 29 not taken.
9 assemblefile(asmname);
562 // RPG Hacker: Necessary, because finishpass() can throws warning and errors.
563
1/4
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 21 not taken.
✓ Branch 12 → 13 taken 9 times.
✗ Branch 12 → 29 not taken.
9 string asmpath = filesystem->create_absolute_path(nullptr, asmname);
564
1/4
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 19 not taken.
✓ Branch 15 → 16 taken 9 times.
✗ Branch 15 → 27 not taken.
9 callstack_push cs_push(callstack_entry_type::FILE, asmpath);
565
1/4
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 17 not taken.
✓ Branch 16 → 17 taken 9 times.
✗ Branch 16 → 25 not taken.
9 finishpass();
566 9 }
567 3 return true;
568 } catch(errfatal&) {
569 return false;
570 }
571 3 };
572 #if defined(RUN_VIA_FIBER)
573 run_as_fiber(execute_patch);
574 #elif defined(RUN_VIA_THREAD)
575
1/4
✗ Branch 376 → 377 not taken.
✗ Branch 376 → 613 not taken.
✓ Branch 514 → 515 taken 3 times.
✗ Branch 514 → 837 not taken.
3 run_as_thread(execute_patch);
576 #else
577 execute_patch();
578 #endif
579
580
1/4
✗ Branch 377 → 378 not taken.
✗ Branch 377 → 613 not taken.
✓ Branch 515 → 516 taken 3 times.
✗ Branch 515 → 837 not taken.
3 closecachedfiles(); // this needs the vfs so do it before destroying it
581
1/4
✗ Branch 378 → 379 not taken.
✗ Branch 378 → 613 not taken.
✓ Branch 516 → 517 taken 3 times.
✗ Branch 516 → 837 not taken.
3 new_filesystem.destroy();
582 3 filesystem = nullptr;
583
584
2/16
✗ Branch 379 → 380 not taken.
✗ Branch 379 → 382 not taken.
✗ Branch 380 → 381 not taken.
✗ Branch 380 → 382 not taken.
✗ Branch 381 → 382 not taken.
✗ Branch 381 → 613 not taken.
✗ Branch 517 → 518 not taken.
✓ Branch 517 → 519 taken 3 times.
✗ Branch 519 → 520 not taken.
✓ Branch 519 → 524 taken 3 times.
✗ Branch 520 → 521 not taken.
✗ Branch 520 → 522 not taken.
✗ Branch 522 → 523 not taken.
✗ Branch 522 → 524 not taken.
✗ Branch 523 → 524 not taken.
✗ Branch 523 → 837 not taken.
3 if (werror && warned) throw_err_null(pass, err_werror);
585
3/10
✗ Branch 382 → 383 not taken.
✗ Branch 382 → 384 not taken.
✗ Branch 383 → 384 not taken.
✗ Branch 383 → 613 not taken.
✗ Branch 524 → 525 not taken.
✓ Branch 524 → 526 taken 3 times.
✓ Branch 526 → 527 taken 3 times.
✗ Branch 526 → 528 not taken.
✓ Branch 527 → 528 taken 3 times.
✗ Branch 527 → 837 not taken.
3 if (checksum_fix_enabled) fixchecksum();
586 //if (pcpos>romlen) romlen=pcpos;
587
2/6
✗ Branch 384 → 385 not taken.
✗ Branch 384 → 393 not taken.
✗ Branch 528 → 529 not taken.
✓ Branch 528 → 530 taken 3 times.
✗ Branch 530 → 531 not taken.
✓ Branch 530 → 539 taken 3 times.
3 if (errored)
588 {
589 if (errnum==0)
590 throw_err_null(pass, err_internal_error, "phantom error");
591 puts("Errors were detected while assembling the patch. Assembling aborted. Your ROM has not been modified.");
592 closerom(false);
593 reseteverything();
594 pause(err);
595 return 1;
596 }
597
2/6
✗ Branch 393 → 394 not taken.
✗ Branch 393 → 405 not taken.
✗ Branch 539 → 540 not taken.
✓ Branch 539 → 541 taken 3 times.
✗ Branch 541 → 542 not taken.
✓ Branch 541 → 555 taken 3 times.
3 if (warned)
598 {
599 if (libcon_interactive)
600 {
601 if (!libcon_question_bool("One or more warnings were detected while assembling the patch. "
602 "Do you want insert the patch anyways? (Default: yes)", true))
603 {
604 puts("ROM left unchanged.");
605 closerom(false);
606 reseteverything();
607 return 1;
608 }
609 }
610 else
611 {
612 if (verbose) puts("Assembling completed, but one or more warnings were detected.");
613 pause(warn);
614 }
615 }
616 else
617 {
618
3/8
✗ Branch 405 → 406 not taken.
✗ Branch 405 → 407 not taken.
✗ Branch 406 → 407 not taken.
✗ Branch 406 → 613 not taken.
✓ Branch 555 → 556 taken 1 time.
✓ Branch 555 → 557 taken 2 times.
✓ Branch 556 → 557 taken 1 time.
✗ Branch 556 → 837 not taken.
3 if (verbose) puts("Assembling completed without problems.");
619
1/8
✗ Branch 407 → 408 not taken.
✗ Branch 407 → 409 not taken.
✗ Branch 408 → 409 not taken.
✗ Branch 408 → 613 not taken.
✗ Branch 557 → 558 not taken.
✓ Branch 557 → 559 taken 3 times.
✗ Branch 558 → 559 not taken.
✗ Branch 558 → 837 not taken.
3 pause(yes);
620 }
621
1/4
✗ Branch 409 → 410 not taken.
✗ Branch 409 → 613 not taken.
✓ Branch 559 → 560 taken 3 times.
✗ Branch 559 → 837 not taken.
3 unsigned int romCrc = closerom();
622
1/4
✗ Branch 411 → 412 not taken.
✗ Branch 411 → 452 not taken.
✗ Branch 561 → 562 not taken.
✓ Branch 561 → 625 taken 3 times.
3 if (symbols)
623 {
624 if (!symfilename) symfilename = get_base_name(romname)+".sym";
625 string contents = create_symbols_file(symbols, romCrc).convert_line_endings_to_native();
626
627 FileHandleType symfile = open_file(symfilename, FileOpenMode_Write);
628
629 if (symfile == InvalidFileHandle)
630 {
631 puts(STR"Failed to create symbols file: \""+symfilename+"\".");
632 pause(err);
633 return 1;
634 }
635 else
636 {
637 write_file(symfile, (const char*)contents, (uint32_t)contents.length());
638 close_file(symfile);
639 }
640 }
641
1/4
✗ Branch 452 → 453 not taken.
✗ Branch 452 → 613 not taken.
✓ Branch 625 → 626 taken 3 times.
✗ Branch 625 → 837 not taken.
3 reseteverything();
642
11/44
✗ Branch 455 → 456 not taken.
✗ Branch 455 → 457 not taken.
✗ Branch 459 → 460 not taken.
✗ Branch 459 → 461 not taken.
✗ Branch 463 → 464 not taken.
✗ Branch 463 → 465 not taken.
✗ Branch 467 → 468 not taken.
✗ Branch 467 → 469 not taken.
✗ Branch 471 → 472 not taken.
✗ Branch 471 → 473 not taken.
✗ Branch 475 → 476 not taken.
✗ Branch 475 → 477 not taken.
✗ Branch 479 → 480 not taken.
✗ Branch 479 → 481 not taken.
✗ Branch 483 → 484 not taken.
✗ Branch 483 → 485 not taken.
✗ Branch 487 → 488 not taken.
✗ Branch 487 → 489 not taken.
✗ Branch 491 → 492 not taken.
✗ Branch 491 → 493 not taken.
✗ Branch 495 → 496 not taken.
✗ Branch 495 → 498 not taken.
✓ Branch 628 → 629 taken 3 times.
✗ Branch 628 → 630 not taken.
✓ Branch 632 → 633 taken 3 times.
✗ Branch 632 → 634 not taken.
✓ Branch 636 → 637 taken 3 times.
✗ Branch 636 → 638 not taken.
✓ Branch 640 → 641 taken 3 times.
✗ Branch 640 → 642 not taken.
✓ Branch 644 → 645 taken 3 times.
✗ Branch 644 → 646 not taken.
✓ Branch 648 → 649 taken 3 times.
✗ Branch 648 → 650 not taken.
✓ Branch 652 → 653 taken 3 times.
✗ Branch 652 → 654 not taken.
✓ Branch 656 → 657 taken 3 times.
✗ Branch 656 → 658 not taken.
✓ Branch 660 → 661 taken 3 times.
✗ Branch 660 → 662 not taken.
✓ Branch 664 → 665 taken 3 times.
✗ Branch 664 → 666 not taken.
✓ Branch 668 → 669 taken 3 times.
✗ Branch 668 → 670 not taken.
3 }
643 catch(errfatal&)
644 {
645 puts("A fatal error was detected while assembling the patch. Assembling aborted. Your ROM has not been modified.");
646 closerom(false);
647 reseteverything();
648 pause(err);
649 return 1;
650 }
651 3 return 0;
652 }
653