asar coverage - build #141


src/asar/
File: src/asar/interface-cli.cpp
Date: 2024-01-23 10:47:37
Lines:
129/226
57.1%
Functions:
4/4
100.0%
Branches:
233/648
36.0%

Line Branch Exec Source
1 #include "asar.h"
2 #include "assocarr.h"
3 #include "libstr.h"
4 #include "libcon.h"
5 #include "libsmw.h"
6 #include "errors.h"
7 #include "warnings.h"
8 #include "platform/file-helpers.h"
9 #include "virtualfile.h"
10 #include "interface-shared.h"
11 #include "assembleblock.h"
12 #include "asar_math.h"
13
14 #ifdef TIMELIMIT
15 # if defined(linux)
16 # include <sys/resource.h>
17 # include <signal.h>
18 # elif defined(_WIN32)
19 //WARNING: The Windows equivalent of SIGXCPU, job limits, is very poorly suited for short-running
20 // tasks like this; it's only checked approximately every seven seconds on the machine I tested on,
21 // and it kills the process instantly once this happens. (Additionally, due to an implementation
22 // quirk, it'll bug up if you ask for anything above about seven minutes, so don't do that.)
23 # include <windows.h>
24 # else
25 # error Time limits not configured for this OS.
26 # endif
27 #endif
28
29 extern const char asarver[];
30
31 32 void print(const char * str)
32 {
33 32 puts(str);
34 32 }
35
36 static FILE * errloc=stderr;
37 static int errnum=0;
38
39 static int max_num_errors = 20;
40
41 234 void error_interface(int errid, int whichpass, const char * e_)
42 {
43 234 errored = true;
44
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 136 times.
234 if (pass == whichpass)
45 {
46 98 errnum++;
47 // don't show current block if the error came from an error command
48
4/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 66 times.
✓ Branch 3 taken 6 times.
98 bool show_block = (thisblock && (errid != error_id_error_command));
49
25/44
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 82 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 82 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 66 times.
✓ Branch 7 taken 16 times.
✓ Branch 8 taken 49 times.
✓ Branch 9 taken 16 times.
✓ Branch 10 taken 49 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 49 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 49 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 49 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 49 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 49 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 49 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 49 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 49 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 33 times.
✓ Branch 29 taken 16 times.
✓ Branch 30 taken 33 times.
✓ Branch 31 taken 16 times.
✓ Branch 32 taken 33 times.
✓ Branch 33 taken 16 times.
✓ Branch 34 taken 33 times.
✓ Branch 35 taken 16 times.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
180 fputs(STR getdecor() + "error: (" + get_error_name((asar_error_id)errid) + "): " + e_ + (show_block ? (STR" [" + thisblock + "]") : STR "") + "\n", errloc);
50
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (errnum == max_num_errors + 1) asar_throw_error(pass, error_type_fatal, error_id_limit_reached, max_num_errors);
51 }
52 234 }
53
54 static bool werror=false;
55 static bool warned=false;
56
57 90 void warn(int errid, const char * e_)
58 {
59 // don't show current block if the warning came from a warn command
60
4/4
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 6 times.
90 bool show_block = (thisblock && (errid != warning_id_warn_command));
61
25/44
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 82 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 82 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 74 times.
✓ Branch 7 taken 8 times.
✓ Branch 8 taken 45 times.
✓ Branch 9 taken 8 times.
✓ Branch 10 taken 45 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 45 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 45 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 45 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 45 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 45 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 45 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 45 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 45 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 37 times.
✓ Branch 29 taken 8 times.
✓ Branch 30 taken 37 times.
✓ Branch 31 taken 8 times.
✓ Branch 32 taken 37 times.
✓ Branch 33 taken 8 times.
✓ Branch 34 taken 37 times.
✓ Branch 35 taken 8 times.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
172 fputs(STR getdecor()+"warning: (" + get_warning_name((asar_warning_id)errid) + "): " + e_ + (show_block ? (STR" [" + thisblock + "]") : STR "") + "\n", errloc);
62 90 warned=true;
63 90 }
64
65 #ifdef TIMELIMIT
66 #if defined(linux)
67 void onsigxcpu(int ignored)
68 {
69 error<errnull>(pass, "Time limit exceeded.");
70 exit(1);
71 }
72 #elif defined(_WIN32)
73 //null
74 #endif
75 #endif
76
77
78
79 190 int main(int argc, char * argv[])
80 {
81 #ifdef TIMELIMIT
82 #if defined(linux)
83 rlimit lim;
84 lim.rlim_cur=TIMELIMIT;
85 lim.rlim_max=RLIM_INFINITY;
86 setrlimit(RLIMIT_CPU, &lim);
87 signal(SIGXCPU, onsigxcpu);
88 #elif defined(_WIN32)
89 HANDLE hjob=CreateJobObject(NULL, nullptr);
90 AssignProcessToJobObject(hjob, GetCurrentProcess());
91 JOBOBJECT_BASIC_LIMIT_INFORMATION jbli;
92 jbli.LimitFlags=JOB_OBJECT_LIMIT_PROCESS_TIME;
93 jbli.PerProcessUserTimeLimit.LowPart=10*1000*1000*TIMELIMIT;
94 jbli.PerProcessUserTimeLimit.HighPart=0;
95 SetInformationJobObject(hjob, JobObjectBasicLimitInformation, &jbli, sizeof(jbli));
96 #endif
97 #endif
98 #define pause(sev) do { if (pause>=pause_##sev) libcon_pause(); } while(0)
99
100 enum {
101 pause_no,
102 pause_err,
103 pause_warn,
104 pause_yes,
105 95 } pause=pause_no;
106
107 enum cmdlparam
108 {
109 cmdlparam_none,
110
111 cmdlparam_addincludepath,
112 cmdlparam_adddefine,
113
114 cmdlparam_count
115 };
116
117 try
118 {
119 190 romdata_r = nullptr;
120
10/20
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 190 times.
✓ Branch 4 taken 95 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 95 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 95 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 95 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 95 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 95 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 95 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 95 times.
✗ Branch 19 not taken.
665 string version=STR"Asar "+dec(asarver_maj)+"."+dec(asarver_min)+((asarver_bug>=10 || asarver_min>=10)?".":"")+
121
5/8
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 95 times.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 95 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 95 times.
✗ Branch 7 not taken.
855 dec(asarver_bug)+(asarver_beta?"pre":"")+", originally developed by Alcaro, maintained by Asar devs.\n"+
122
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
190 "Source code: https://github.com/RPGHacker/asar\n";
123 190 char * myname=argv[0];
124
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 if (strrchr(myname, '/')) myname=strrchr(myname, '/')+1;
125 //char * dot=strrchr(myname, '.');
126 //if (dot) *dot='\0';
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
190 if (!strncasecmp(myname, "xkas", strlen("xkas"))) {
128 // RPG Hacker: no asar_throw_Warning() here, because we didn't have a chance to disable warnings yet.
129 // Also seems like warning aren't even registered at this point yet.
130 puts("Warning: xkas support is being deprecated and will be removed in the next release of asar!!!");
131 puts("(this was triggered by renaming asar.exe to xkas.exe, which activated a compatibility feature.)");
132 errloc=stdout;
133 }
134 //if (dot) *dot='.';
135
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 libcon_init(argc, argv,
136 "[options] asm_file [rom_file]\n\n"
137 "Supported options:\n\n"
138 " --version \n"
139 " Display version information.\n\n"
140 " -v, --verbose \n"
141 " Enable verbose mode.\n\n"
142 " --symbols=<none/wla/nocash>\n"
143 " Specifies the format of the symbols output file. (Default is none for no symbols file)\n\n"
144 " --symbols-path=<filename>\n"
145 " Override the default path to the symbols output file. The default is the ROM's base name with an\n"
146 " extension of '.sym'.\n\n"
147 " --no-title-check\n"
148 " Disable verifying ROM title. (Note that irresponsible use will likely corrupt your ROM)\n\n"
149 " --pause-mode=<never/on-error/on-warning/always>\n"
150 " Specify when Asar should pause the application. (Never, on error, on warning or always)\n\n"
151 " --fix-checksum=<on/off>\n"
152 " Override Asar's checksum generation, allowing you to manually enable/disable generating a checksum\n\n"
153 " -I<path> \n"
154 " --include <path> \n"
155 " Add an include search path to Asar.\n\n"
156 " -D<def>[=<val>] \n"
157 " --define <def>[=<val>]\n"
158 " Add a define (optionally with a value) to Asar.\n\n"
159 " -werror \n"
160 " Treat warnings as errors.\n\n"
161 " -w<name> \n"
162 " Enable a specific warning.\n\n"
163 " -wno<name> \n"
164 " Disable a specific warning.\n\n"
165 " --error-limit=<N> \n"
166 " Stop after encountering this many errors, instead of the default 20\n\n"
167 );
168 190 ignoretitleerrors=false;
169 95 string par;
170 190 bool verbose=libcon_interactive;
171
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 string symbols="";
172
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 string symfilename="";
173
174 95 autoarray<string> includepaths;
175 95 autoarray<const char*> includepath_cstrs;
176
177
6/8
✓ Branch 0 taken 950 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 855 times.
✓ Branch 3 taken 95 times.
✓ Branch 4 taken 475 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 380 times.
✓ Branch 7 taken 95 times.
1425 while ((par=libcon_option()))
178 {
179 380 cmdlparam postprocess_param = cmdlparam_none;
180 380 const char* postprocess_arg = nullptr;
181
182 #define checkstartmatch(arg, stringliteral) (!strncmp(arg, stringliteral, strlen(stringliteral)))
183
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 760 times.
760 if (par=="--no-title-check") ignoretitleerrors=true;
185
4/6
✓ Branch 0 taken 760 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 380 times.
✓ Branch 3 taken 380 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 380 times.
760 else if (par == "-v" || par=="--verbose") verbose=true;
186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 760 times.
760 else if (checkstartmatch(par, "--symbols="))
187 {
188 if (par == "--symbols=none") symbols = "";
189 else if (par=="--symbols=wla") symbols="wla";
190 else if (par=="--symbols=nocash") symbols="nocash";
191 else libcon_badusage();
192 }
193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 760 times.
760 else if (checkstartmatch(par, "--symbols-path=")) {
194 symfilename=((const char*)par) + strlen("--symbols-path=");
195 }
196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 760 times.
760 else if (checkstartmatch(par, "--error-limit="))
197 {
198 char* out;
199 long lim = strtol((const char*)par + strlen("--error-limit="), &out, 10);
200 max_num_errors = lim;
201 }
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 760 times.
760 else if (par=="--version")
203 {
204 puts(version);
205 return 0;
206 }
207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 760 times.
760 else if (checkstartmatch(par, "--pause-mode="))
208 {
209 if (par=="--pause-mode=never") pause=pause_no;
210 else if (par=="--pause-mode=on-error") pause=pause_err;
211 else if (par=="--pause-mode=on-warning") pause=pause_warn;
212 else if (par=="--pause-mode=always") pause=pause_yes;
213 else libcon_badusage();
214 }
215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 760 times.
760 else if(checkstartmatch(par, "--fix-checksum=")) {
216 if(par=="--fix-checksum=on") {
217 force_checksum_fix = true;
218 checksum_fix_enabled = true;
219 } else if(par=="--fix-checksum=off") {
220 force_checksum_fix = true;
221 checksum_fix_enabled = false;
222 } else libcon_badusage();
223 }
224
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 570 times.
760 else if (checkstartmatch(par, "-I"))
225 {
226 95 postprocess_param = cmdlparam_addincludepath;
227 190 postprocess_arg = ((const char*)par) + strlen("-I");
228 }
229
2/2
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 190 times.
570 else if (checkstartmatch(par, "-D"))
230 {
231 190 postprocess_param = cmdlparam_adddefine;
232 380 postprocess_arg = ((const char*)par) + strlen("-D");
233 }
234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
190 else if (par == "--include")
235 {
236 postprocess_arg = libcon_option_value();
237 if (postprocess_arg != nullptr)
238 {
239 postprocess_param = cmdlparam_addincludepath;
240 }
241 }
242
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 else if (par == "--define")
243 {
244
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 postprocess_arg = libcon_option_value();
245
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 95 times.
190 if (postprocess_arg != nullptr)
246 {
247 95 postprocess_param = cmdlparam_adddefine;
248 }
249 }
250 else if (checkstartmatch(par, "-w"))
251 {
252 const char* w_param = ((const char*)par) + strlen("-w");
253
254 if (checkstartmatch(w_param, "error"))
255 {
256 werror = true;
257 }
258 else if (checkstartmatch(w_param, "no"))
259 {
260 asar_warning_id warnid = parse_warning_id_from_string(w_param + strlen("no"));
261
262 if (warnid != warning_id_end)
263 {
264 set_warning_enabled(warnid, false);
265 }
266 else
267 {
268 asar_throw_error(pass, error_type_null, error_id_invalid_warning_id, "-wno", (int)(warning_id_start + 1), (int)(warning_id_end - 1));
269 }
270 }
271 else
272 {
273 asar_warning_id warnid = parse_warning_id_from_string(w_param);
274
275 if (warnid != warning_id_end)
276 {
277 set_warning_enabled(warnid, true);
278 }
279 else
280 {
281 asar_throw_error(pass, error_type_null, error_id_invalid_warning_id, "-w", (int)(warning_id_start + 1), (int)(warning_id_end - 1));
282 }
283 }
284
285 }
286 else libcon_badusage();
287
288
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 570 times.
760 if (postprocess_param == cmdlparam_addincludepath)
289 {
290
2/4
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
190 includepaths.append(postprocess_arg);
291 }
292
1/2
✓ Branch 0 taken 570 times.
✗ Branch 1 not taken.
570 else if (postprocess_param == cmdlparam_adddefine)
293 {
294
2/2
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 190 times.
570 if (strchr(postprocess_arg, '=') != nullptr)
295 {
296 // argument contains value, not only name
297 190 const char* eq_loc = strchr(postprocess_arg, '=');
298
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
380 string name = string(postprocess_arg, (int)(eq_loc - postprocess_arg));
299
2/4
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 190 times.
✗ Branch 3 not taken.
380 name = strip_whitespace(name);
300
2/4
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 190 times.
✗ Branch 3 not taken.
380 name = strip_prefix(name, '!', false); // remove leading ! if present
301
302
2/6
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 380 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
380 if (!validatedefinename(name)) asar_throw_error(pass, error_type_null, error_id_cmdl_define_invalid, "command line defines", name.data());
303
304
3/4
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 190 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 190 times.
380 if (clidefines.exists(name)) {
305 asar_throw_error(pass, error_type_null, error_id_cmdl_define_override, "Command line define", name.data());
306 pause(err);
307 return 1;
308 }
309
2/4
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 190 times.
✗ Branch 3 not taken.
380 clidefines.create(name) = eq_loc + 1;
310
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
380 }
311 else
312 {
313 // argument doesn't have a value, only name
314
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 string name = postprocess_arg;
315
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
190 name = strip_whitespace(name);
316
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
190 name = strip_prefix(name, '!', false); // remove leading ! if present
317
318
2/6
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 190 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
190 if (!validatedefinename(name)) asar_throw_error(pass, error_type_null, error_id_cmdl_define_invalid, "command line defines", name.data());
319
320
3/4
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 95 times.
190 if (clidefines.exists(name)) {
321 asar_throw_error(pass, error_type_null, error_id_cmdl_define_override, "Command line define", name.data());
322 pause(err);
323 return 1;
324 }
325
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
190 clidefines.create(name) = "";
326
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
190 }
327 }
328 }
329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
190 if (verbose)
330 {
331 puts(version);
332 }
333
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
190 string asmname=libcon_require_filename("Enter patch name:");
334
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
190 string romname=libcon_optional_filename("Enter ROM name:", nullptr);
335 //char * outname=libcon_optional_filename("Enter output ROM name:", nullptr);
336
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 libcon_end();
337
2/10
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 95 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
190 if (!strchr(asmname, '.') && !file_exists(asmname)) asmname+=".asm";
338
3/4
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 95 times.
190 if (!romname)
339 {
340 string romnametmp = get_base_name(asmname);
341 if (file_exists(romnametmp+".sfc")) romname=romnametmp+".sfc";
342 else if (file_exists(romnametmp+".smc")) romname=romnametmp+".smc";
343 else romname=STR romnametmp+".sfc";
344 }
345
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 95 times.
190 else if (!strchr(romname, '.') && !file_exists(romname))
346 {
347 if (file_exists(STR romname+".sfc")) romname+=".sfc";
348 else if (file_exists(STR romname+".smc")) romname+=".smc";
349 }
350
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 190 times.
190 if (!file_exists(romname))
351 {
352 FILE * f=fopen(romname, "wb");
353 if (!f)
354 {
355 asar_throw_error(pass, error_type_fatal, error_id_create_rom_failed);
356 }
357 fclose(f);
358 }
359
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 190 times.
190 if (!openrom(romname, false))
360 {
361 thisfilename= nullptr;
362 asar_throw_error(pass, error_type_null, openromerror);
363 pause(err);
364 return 1;
365 }
366 //check if the ROM title and checksum looks sane
367
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 142 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
190 if (romlen>=32768 && !ignoretitleerrors)
368 {
369
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 bool validtitle=setmapper();
370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (!validtitle)
371 {
372 string title;
373 for (int i=0;i<21;i++)
374 {
375 unsigned char c=romdata[snestopc(0x00FFC0+i)];
376 if (c==7) c=14;
377 if (c==8) c=27;//to not generate more hard-to-print characters than needed
378 if (c==9) c=26;//random characters are picked in accordance with the charset Windows-1252, but they should be garbage in all charsets
379 if (c=='\r') c=17;
380 if (c=='\n') c=25;
381 if (c=='\0') c=155;
382 title+=(char)c;
383 }
384 if (libcon_interactive)
385 {
386 if (!libcon_question_bool(STR"Warning: The ROM title appears to be \""+title+"\", which looks like garbage. "
387 "Is this your ROM title? (Note that inproperly answering \"yes\" will crash your ROM.)", false))
388 {
389 puts("Assembling aborted. snespurify should be able to fix your ROM.");
390 return 1;
391 }
392 }
393 else
394 {
395 puts(STR"Error: The ROM title appears to be \""+title+"\", which looks like garbage. "
396 "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.");
397 pause(err);
398 return 1;
399 }
400 }
401 }
402
403
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 190 times.
✗ Branch 3 not taken.
285 string stdincludespath = STR dir(argv[0]) + "stdincludes.txt";
404
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 parse_std_includes(stdincludespath, includepaths);
405
406
2/2
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 190 times.
570 for (int i = 0; i < includepaths.count; ++i)
407 {
408
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 190 times.
✗ Branch 3 not taken.
380 includepath_cstrs.append((const char*)includepaths[i]);
409 }
410
411 190 size_t includepath_count = (size_t)includepath_cstrs.count;
412
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 virtual_filesystem new_filesystem;
413
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
190 new_filesystem.initialize(&includepath_cstrs[0], includepath_count);
414 190 filesystem = &new_filesystem;
415
416
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 190 times.
✗ Branch 3 not taken.
285 string stddefinespath = STR dir(argv[0]) + "stddefines.txt";
417
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 parse_std_defines(stddefinespath);
418
419
2/2
✓ Branch 0 taken 562 times.
✓ Branch 1 taken 186 times.
748 for (pass=0;pass<3;pass++)
420 {
421 //pass 1: find which bank all labels are in, for label optimizations
422 // freespaces are listed as above 0xFFFFFF, to find if it's in the ROM or if it's dynamic
423 //pass 2: find where exactly all labels are
424 //pass 3: assemble it all
425
1/2
✓ Branch 0 taken 562 times.
✗ Branch 1 not taken.
562 initstuff();
426
2/2
✓ Branch 0 taken 558 times.
✓ Branch 1 taken 4 times.
562 assemblefile(asmname, true);
427
1/2
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
558 finishpass();
428 }
429
430
1/2
✓ Branch 0 taken 186 times.
✗ Branch 1 not taken.
186 closecachedfiles(); // this needs the vfs so do it before destroying it
431
1/2
✓ Branch 0 taken 186 times.
✗ Branch 1 not taken.
186 new_filesystem.destroy();
432 186 filesystem = nullptr;
433
434
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 186 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
186 if (werror && warned) asar_throw_error(pass, error_type_null, error_id_werror);
435
3/4
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 176 times.
✗ Branch 3 not taken.
186 if (checksum_fix_enabled) fixchecksum();
436 //if (pcpos>romlen) romlen=pcpos;
437
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 146 times.
186 if (errored)
438 {
439
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 puts("Errors were detected while assembling the patch. Assembling aborted. Your ROM has not been modified.");
440
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 closerom(false);
441
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 reseteverything();
442
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
40 pause(err);
443 40 return 1;
444 }
445
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 118 times.
146 if (warned)
446 {
447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (libcon_interactive)
448 {
449 if (!libcon_question_bool("One or more warnings were detected while assembling the patch. "
450 "Do you want insert the patch anyways? (Default: yes)", true))
451 {
452 puts("ROM left unchanged.");
453 closerom(false);
454 reseteverything();
455 return 1;
456 }
457 }
458 else
459 {
460
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
28 if (verbose) puts("Assembling completed, but one or more warnings were detected.");
461
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
28 pause(warn);
462 }
463 }
464 else
465 {
466
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
118 if (verbose) puts("Assembling completed without problems.");
467
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
118 pause(yes);
468 }
469
1/2
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
146 unsigned int romCrc = closerom();
470
3/4
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 73 times.
146 if (symbols)
471 {
472 if (!symfilename) symfilename = get_base_name(romname)+".sym";
473 string contents = create_symbols_file(symbols, romCrc);
474 FILE * symfile = fopen(symfilename, "wt");
475 if (!symfile)
476 {
477 puts(STR"Failed to create symbols file: \"" + symfilename + "\".");
478 pause(err);
479 return 1;
480 }
481 else
482 {
483 fputs(contents, symfile);
484 fclose(symfile);
485 }
486 }
487
1/2
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
146 reseteverything();
488
22/22
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 73 times.
✓ Branch 5 taken 20 times.
✓ Branch 6 taken 73 times.
✓ Branch 7 taken 20 times.
✓ Branch 8 taken 73 times.
✓ Branch 9 taken 20 times.
✓ Branch 10 taken 73 times.
✓ Branch 11 taken 20 times.
✓ Branch 12 taken 73 times.
✓ Branch 13 taken 20 times.
✓ Branch 14 taken 73 times.
✓ Branch 15 taken 20 times.
✓ Branch 16 taken 73 times.
✓ Branch 17 taken 20 times.
✓ Branch 18 taken 73 times.
✓ Branch 19 taken 20 times.
✓ Branch 20 taken 73 times.
✓ Branch 21 taken 20 times.
450 }
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 catch(errfatal&)
490 {
491
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 puts("A fatal error was detected while assembling the patch. Assembling aborted. Your ROM has not been modified.");
492
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 closerom(false);
493
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 reseteverything();
494
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 pause(err);
495 2 return 1;
496 4 }
497 146 return 0;
498 }
499