asar coverage - build #93


src/asar/
File: src/asar/assembleblock.cpp
Date: 2024-01-19 18:20:15
Lines:
1286/1403
91.7%
Functions:
41/41
100.0%
Branches:
1548/2477
62.5%

Line Branch Exec Source
1 #include "addr2line.h"
2 #include "asar.h"
3 #include "assembleblock.h"
4 #include "asar_math.h"
5 #include "macro.h"
6 #include "platform/file-helpers.h"
7 #include "table.h"
8 #include "unicode.h"
9 #include <cinttypes>
10
11 #include "interface-shared.h"
12 #include "arch-shared.h"
13
14 int arch=arch_65816;
15
16 bool snespos_valid = false;
17 int snespos;
18 int realsnespos;
19 int startpos;
20 int realstartpos;
21
22 bool mapper_set = false;
23 bool warn_endwhile = true;
24 int label_counter = 0;
25
26 static int old_snespos;
27 static int old_startpos;
28 static int old_optimizeforbank;
29 static bool old_snespos_valid;
30 static int struct_base;
31 static string struct_name;
32 static string struct_parent;
33 static bool in_struct = false;
34 static bool in_sub_struct = false;
35 static bool static_struct = false;
36 static bool in_spcblock = false;
37
38 assocarr<snes_struct> structs;
39
40 static bool movinglabelspossible = false;
41
42 static bool disable_bank_cross_errors = false;
43 static bool check_half_banks_crossed = false;
44
45 int bytes;
46 static int freespaceuse=0;
47
48 static enum {
49 ratsmeta_ban,
50 ratsmeta_allow,
51 ratsmeta_used,
52 } ratsmetastate=ratsmeta_ban;
53
54 enum spcblock_type{
55 spcblock_nspc,
56 spcblock_custom
57 };
58
59 struct spcblock_data{
60 unsigned int destination;
61 spcblock_type type;
62 string macro_name;
63
64 unsigned int execute_address;
65 unsigned int size_address;
66 mapper_t old_mapper;
67 }spcblock;
68
69 460 int snestopc_pick(int addr)
70 {
71 1080 return snestopc(addr);
72 }
73
74 1309128 inline void verifysnespos()
75 {
76
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1309128 times.
1309128 if (!snespos_valid)
77 {
78 asar_throw_error(0, error_type_block, error_id_missing_org);
79 snespos=0x008000;
80 realsnespos=0x008000;
81 startpos=0x008000;
82 realstartpos=0x008000;
83 snespos_valid = true;
84 }
85 1309128 }
86
87 1656 static int fixsnespos(int inaddr, int step)
88 {
89 // randomdude999: turns out it wasn't very reliable at all.
90 /* // RPG Hacker: No idea how reliable this is.
91 // Might not work with some of the more exotic mappers.
92 return pctosnes(snestopc(inaddr) + step); */
93
2/2
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 1368 times.
1656 if (mapper == lorom) {
94
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 252 times.
288 if ((inaddr&0xFFFF)+step > 0xFFFF) {
95 // bank crossed
96 36 return inaddr+step+0x8000;
97 }
98 252 return inaddr+step;
99 } else if (mapper == hirom) {
100 if ((inaddr&0x400000) == 0) {
101 // system pages, need to account for low pages and stuff
102 if ((inaddr&0xFFFF)+step > 0xFFFF) {
103 return inaddr+step+0x8000;
104 }
105 }
106 return inaddr+step;
107 } else if (mapper == exlorom) {
108 // exlorom has no mirroring so this should work fine
109 return pctosnes(snestopc(inaddr)+step);
110 } else if (mapper == exhirom) {
111 // apparently exhirom is pretty similar to hirom after all
112 if ((inaddr&0x400000) == 0) {
113 // system pages, need to account for low pages and stuff
114 if ((inaddr&0xFFFF)+step > 0xFFFF) {
115 return inaddr+step+0x8000;
116 }
117 }
118 return inaddr+step;
119 } else if (mapper == sa1rom) {
120 if((inaddr&0x400000) == 0) {
121 // lorom area
122 if ((inaddr&0xFFFF)+step > 0xFFFF) {
123 return inaddr+step+0x8000;
124 }
125 return inaddr+step;
126 } else {
127 // hirom area
128 return inaddr+step;
129 }
130 } else if (mapper == sfxrom) {
131 if ((inaddr&0x400000) == 0) {
132 // lorom area
133 if ((inaddr&0xFFFF)+step > 0xFFFF) {
134 return inaddr+step+0x8000;
135 }
136 } else {
137 // hirom area
138 return inaddr+step;
139 }
140 } else if (mapper == bigsa1rom) {
141 // no mirrors here, so this should work
142 return pctosnes(snestopc(inaddr)+step);
143 } else if (mapper == norom) {
144 1368 return inaddr+step;
145 }
146 return -1;
147 }
148
149 1308099 inline void step(int num)
150 {
151
2/2
✓ Branch 0 taken 828 times.
✓ Branch 1 taken 1307271 times.
1308099 if (disable_bank_cross_errors)
152 {
153 828 snespos = fixsnespos(snespos, num);
154 828 realsnespos = fixsnespos(realsnespos, num);
155
156 // RPG Hacker: Not adjusting startpos here will eventually throw
157 // an error in checkbankcross() if we set warn bankcross on again.
158 // As far as I can tell, those are pretty much just used for
159 // checking bank crossing, anyways, so it's hopefully save to just
160 // adjust them here.
161 828 startpos = snespos;
162 828 realstartpos = realsnespos;
163 }
164 else
165 {
166 1307271 snespos += num;
167 1307271 realsnespos += num;
168 }
169 1308099 bytes+=num;
170 1308099 }
171
172 1306299 inline void write1_65816(unsigned int num)
173 {
174 1306299 verifysnespos();
175
2/2
✓ Branch 0 taken 435341 times.
✓ Branch 1 taken 870958 times.
1306299 if (pass==2)
176 {
177 435341 int pcpos=snestopc(realsnespos&0xFFFFFF);
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 435341 times.
435341 if (pcpos<0)
179 {
180 movinglabelspossible=true;
181 asar_throw_error(2, error_type_block, error_id_snes_address_doesnt_map_to_rom, hex((unsigned int)realsnespos, 6).data());
182 }
183 435341 writeromdata_byte(pcpos, (unsigned char)num);
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 435341 times.
435341 if (pcpos>=romlen) romlen=pcpos+1;
185 }
186
4/4
✓ Branch 0 taken 435461 times.
✓ Branch 1 taken 870838 times.
✓ Branch 2 taken 26531 times.
✓ Branch 3 taken 408930 times.
1306299 if(pass == 1 && freespaceid == 0) {
187 26531 int pcpos = snestopc(realsnespos & 0xFFFFFF);
188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26531 times.
26531 if(pcpos < 0) asar_throw_error(pass, error_type_fatal, error_id_internal_error, "invalid pos in pass 1");
189 26531 addromwrite(pcpos, 1);
190
2/2
✓ Branch 0 taken 25910 times.
✓ Branch 1 taken 621 times.
26531 if (pcpos>=romlen) romlen=pcpos+1;
191 }
192 1306299 step(1);
193 1306299 ratsmetastate=ratsmeta_ban;
194 1306299 }
195
196 int recent_opcode_num = 0;
197
198 476669 void write1_pick(unsigned int num)
199 {
200
9/18
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 96 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 96 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 96 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 96 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 96 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 96 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 96 times.
✗ Branch 17 not taken.
477533 write1_65816(num);
201 1250972 }
202
203 77916 static bool asblock_pick(char** word, int numwords)
204 {
205 77916 recent_opcode_num = 1;
206
207
2/2
✓ Branch 0 taken 59844 times.
✓ Branch 1 taken 18072 times.
77916 if (arch==arch_65816) return asblock_65816(word, numwords);
208
2/2
✓ Branch 0 taken 7110 times.
✓ Branch 1 taken 10962 times.
18072 if (arch==arch_spc700) return asblock_spc700(word, numwords);
209
1/2
✓ Branch 0 taken 10962 times.
✗ Branch 1 not taken.
10962 if (arch==arch_superfx) return asblock_superfx(word, numwords);
210 return true;
211 }
212
213 #define write1 write1_pick
214 #define snestopc snestopc_pick
215
216 22284 const char * safedequote(char * str)
217 {
218 22284 const char * tmp=dequote(str);
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22284 times.
22284 if (!tmp) asar_throw_error(0, error_type_block, error_id_garbage_near_quoted_string);
220 22284 return tmp;
221 }
222
223 extern char romtitle[30];
224 extern bool stdlib;
225
226 5184 void write2(unsigned int num)
227 {
228 1732 write1(num);
229 5184 write1(num/256);
230 5184 }
231
232 3162 void write3(unsigned int num)
233 {
234 1052 write1(num);
235 3162 write1(num/256);
236 3162 write1(num/65536);
237 3162 }
238
239 342 void write4(unsigned int num)
240 {
241 114 write1(num);
242 342 write1(num/256);
243 342 write1(num/65536);
244 342 write1(num/16777216);
245 342 }
246
247 //these are NOT used by the math parser - see math.cpp for that
248 90 int read2(int insnespos)
249 {
250 30 int addr=snestopc(insnespos);
251
3/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
90 if (addr<0 || addr+2>romlen_r) return -1;
252 return
253 72 romdata_r[addr ] |
254 72 (romdata_r[addr+1]<< 8);
255 }
256
257 216 int read3(int insnespos)
258 {
259 72 int addr=snestopc(insnespos);
260
2/4
✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 216 times.
✗ Branch 3 not taken.
216 if (addr<0 || addr+3>romlen_r) return -1;
261 return
262 216 romdata_r[addr ] |
263 216 (romdata_r[addr+1]<< 8)|
264 216 (romdata_r[addr+2]<<16);
265 }
266
267 4266 int getlenfromchar(char c)
268 {
269 4266 c=(char)to_lower(c);
270
2/2
✓ Branch 0 taken 2286 times.
✓ Branch 1 taken 1980 times.
4266 if (c=='b') return 1;
271
2/2
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 1980 times.
2286 if (c=='w') return 2;
272
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 288 times.
306 if (c=='l') return 3;
273 18 asar_throw_error(0, error_type_block, error_id_invalid_opcode_length);
274 return -1;
275 }
276
277 assocarr<snes_label> labels;
278 static autoarray<int> poslabels;
279 static autoarray<int> neglabels;
280
281 autoarray<int>* macroposlabels;
282 autoarray<int>* macroneglabels;
283
284 autoarray<string> sublabels;
285 autoarray<string>* macrosublabels;
286
287 // randomdude999: ns is still the string to prefix to all labels, it's calculated whenever namespace_list is changed
288 string ns;
289 string ns_backup;
290 autoarray<string> namespace_list;
291
292 //bool fastrom=false;
293
294 autoarray<string> includeonce;
295
296 // data necessary for one freespace block
297 1537 struct freespace_data {
298 // snespos of the start of the freespace block. set to the found freespace
299 // block during the `freespace` command in pass 1.
300 int pos;
301 // length of the freespace block
302 int len;
303 // whether this freespace is leaked (no autocleans pointing at it)
304 bool leaked;
305 // position of the previous version of this freespace
306 int orgpos;
307 // length of previous version
308 int orglen;
309 // whether this freespace is static, i.e. can't be relocated when reinserting
310 bool is_static;
311 // what byte to use when searching for freespace, and clearing out previous rats tags
312 unsigned char cleanbyte;
313
314 // options only used for finding freespace:
315
316 // if this freespace is pinned to another one, this holds the name of the label of the target.
317 // we can't resolve this into a freespace number earlier since it could be a forward reference.
318 // we also need to keep the current namespace around since this is necessary for resolving label references.
319 string pin_target;
320 string pin_target_ns;
321 // computed at the end of pass 0. this is the freespace id of the final pin
322 // target, in case of multiple "nested" pins or whatnot.
323 int pin_target_id;
324 // what address to start searching for freespace at
325 int search_start;
326 // what bank to search for freespace in: -1 for any bank, -2 for banks with
327 // code mirrors, positive for specific bank
328 int bank;
329 bool write_rats;
330 // should rework this...
331 bool flag_align;
332 // hack for incbin -> label
333 bool dont_find;
334 // pinned freespaces: how much space is actually needed for this freespace
335 int total_len;
336 // pinned freespaces: how much of this block we've already used
337 int used_len;
338 };
339 static autoarray<freespace_data> freespaces;
340
341 // id of the next unused freespace.
342 static int freespaceidnext;
343 // id of the current freespace, or 0 if not in freespace.
344 int freespaceid;
345 // start address of the current freespace, used for computing the length of the
346 // current freespace.
347 static int freespacestart;
348
349
350 7341 bool confirmname(const char * name)
351 {
352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7341 times.
7341 if (!name[0]) return false;
353
2/2
✓ Branch 0 taken 1836 times.
✓ Branch 1 taken 5505 times.
7341 if (is_digit(name[0])) return false;
354
2/2
✓ Branch 0 taken 45957 times.
✓ Branch 1 taken 5487 times.
51444 for (int i=0;name[i];i++)
355 {
356
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 45939 times.
45957 if (!is_ualnum(name[i])) return false;
357 }
358 return true;
359 }
360
361 155464 string posneglabelname(const char ** input, bool define)
362 {
363 155464 const char* label = *input;
364
365 71140 string output;
366
367 int depth = 0;
368 bool ismacro = false;
369
370
2/2
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 155326 times.
155464 if (label[0] == '?')
371 {
372 ismacro = true;
373 138 label++;
374 }
375
4/4
✓ Branch 0 taken 163 times.
✓ Branch 1 taken 155301 times.
✓ Branch 2 taken 583 times.
✓ Branch 3 taken 154718 times.
155464 if (label[0] == '-' || label[0] == '+')
376 {
377 char first = label[0];
378
4/4
✓ Branch 0 taken 926 times.
✓ Branch 1 taken 566 times.
✓ Branch 2 taken 746 times.
✓ Branch 3 taken 180 times.
1492 for (depth = 0; label[0] && label[0] == first; depth++) label++;
379
380
2/2
✓ Branch 0 taken 698 times.
✓ Branch 1 taken 48 times.
746 if (!ismacro)
381 {
382
2/2
✓ Branch 0 taken 559 times.
✓ Branch 1 taken 139 times.
698 if (first == '+')
383 {
384 559 *input = label;
385 1118 output = STR":pos_" + dec(depth) + "_" + dec(poslabels[depth]);
386
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 250 times.
868 if (define) poslabels[depth]++;
387 }
388 else
389 {
390 139 *input = label;
391
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 118 times.
160 if (define) neglabels[depth]++;
392 278 output = STR":neg_" + dec(depth) + "_" + dec(neglabels[depth]);
393 }
394 }
395 else
396 {
397
3/6
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 48 times.
48 if (macrorecursion == 0 || macroposlabels == nullptr || macroneglabels == nullptr)
398 {
399 if (!macrorecursion) asar_throw_error(0, error_type_block, error_id_macro_label_outside_of_macro);
400 }
401 else
402 {
403
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
48 if (first == '+')
404 {
405 24 *input = label;
406 48 output = STR":macro_" + dec(calledmacros) + "_pos_" + dec(depth) + "_" + dec((*macroposlabels)[depth]);
407
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
24 if (define) (*macroposlabels)[depth]++;
408 }
409 else
410 {
411 24 *input = label;
412
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
42 if (define) (*macroneglabels)[depth]++;
413 48 output = STR":macro_" + dec(calledmacros) + "_neg_" + dec(depth) + "_" + dec((*macroneglabels)[depth]);
414 }
415 }
416 }
417 }
418
419 155464 return output;
420 }
421
422 6295 static string labelname(const char ** rawname, bool define=false)
423 {
424 #define deref_rawname (*rawname)
425 autoarray<string>* sublabellist = &sublabels;
426
427 6295 bool ismacro = (deref_rawname[0] == '?');
428 bool issublabel = false;
429
430
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 6223 times.
6295 if (ismacro)
431 {
432 72 deref_rawname++;
433 72 sublabellist = macrosublabels;
434 }
435
436 3156 string name;
437 int i=-1;
438
439
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6295 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6295 if (is_digit(*deref_rawname)) asar_throw_error(1, error_type_block, error_id_invalid_label_name);
440
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 6085 times.
6295 if (*deref_rawname ==':')
441 {
442 210 deref_rawname++;
443 name=":";
444 }
445
4/4
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 5491 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 5419 times.
6085 else if (!in_struct && !in_sub_struct)
446 {
447
2/2
✓ Branch 0 taken 285 times.
✓ Branch 1 taken 5419 times.
5704 for (i=0;(*deref_rawname =='.');i++) deref_rawname++;
448
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5419 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5419 if (!is_ualnum(*deref_rawname)) asar_throw_error(1, error_type_block, error_id_invalid_label_name);
449
2/2
✓ Branch 0 taken 267 times.
✓ Branch 1 taken 5152 times.
5419 if (i)
450 {
451
2/6
✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 267 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
267 if (!sublabellist || !(*sublabellist)[i - 1]) asar_throw_error(1, error_type_block, error_id_label_missing_parent);
452 534 name+=STR(*sublabellist)[i-1]+"_";
453 issublabel = true;
454 }
455 }
456
457
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 6247 times.
6295 if (ismacro && !issublabel)
458 {
459 // RPG Hacker: Don't add the prefix for sublabels, because they already inherit it from
460 // their parents' names.
461
4/6
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
48 if (!macrorecursion || macrosublabels == nullptr) asar_throw_error(1, error_type_block, error_id_macro_label_outside_of_macro);
462 60 name = STR":macro_" + dec(calledmacros) + "_" + name;
463 }
464
465
466
4/4
✓ Branch 0 taken 5683 times.
✓ Branch 1 taken 594 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 5611 times.
6277 if (in_struct || in_sub_struct)
467 {
468
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 594 times.
666 if(in_sub_struct)
469 {
470 72 name += struct_parent + ".";
471 }
472 666 name += struct_name;
473 666 name += '.';
474
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 648 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
666 if(*deref_rawname != '.') asar_throw_error(1, error_type_block, error_id_invalid_label_name); //probably should be a better error. TODO!!!
475 648 deref_rawname++;
476 }
477
478
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6259 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6259 if (!is_ualnum(*deref_rawname)) asar_throw_error(1, error_type_block, error_id_invalid_label_name);
479
480
4/4
✓ Branch 0 taken 44190 times.
✓ Branch 1 taken 6745 times.
✓ Branch 2 taken 486 times.
✓ Branch 3 taken 6259 times.
50935 while (is_ualnum(*deref_rawname) || *deref_rawname == '.')
481 {
482 44676 name+=*(deref_rawname++);
483 }
484
485
4/4
✓ Branch 0 taken 2463 times.
✓ Branch 1 taken 3796 times.
✓ Branch 2 taken 3628 times.
✓ Branch 3 taken 168 times.
6259 if(!define && *deref_rawname == '[')
486 {
487
3/4
✓ Branch 0 taken 552 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 384 times.
✓ Branch 3 taken 168 times.
552 while (*deref_rawname && *deref_rawname != ']') deref_rawname++;
488
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
168 if(*deref_rawname != ']') asar_throw_error(1, error_type_block, error_id_invalid_label_missing_closer);
489 168 deref_rawname++;
490
1/4
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
168 if(*deref_rawname != '.') asar_throw_error(1, error_type_block, error_id_invalid_label_name);
491 }
492
493
4/4
✓ Branch 0 taken 672 times.
✓ Branch 1 taken 6427 times.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 6259 times.
7099 while (is_ualnum(*deref_rawname) || *deref_rawname == '.')
494 {
495 840 name+=*(deref_rawname++);
496 }
497
498
3/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 6187 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 72 times.
6259 if(*deref_rawname == '[') asar_throw_error(2, error_type_block, error_id_invalid_subscript);
499
500
2/2
✓ Branch 0 taken 1761 times.
✓ Branch 1 taken 4426 times.
6187 if (define && i>=0)
501 {
502 1761 (*sublabellist).reset(i);
503 (*sublabellist)[i]=name;
504 }
505 6187 return name;
506 #undef deref_rawname
507 108 }
508
509 3652 inline bool labelvalcore(const char ** rawname, snes_label * rval, bool define, bool shouldthrow)
510 {
511 3652 string name=labelname(rawname, define);
512
4/4
✓ Branch 0 taken 182 times.
✓ Branch 1 taken 3470 times.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 3556 times.
3930 if (ns && labels.exists(ns+name)) {*rval = labels.find(ns+name);}
513
2/2
✓ Branch 0 taken 3123 times.
✓ Branch 1 taken 433 times.
3556 else if (labels.exists(name)) {*rval = labels.find(name);}
514 else
515 {
516
4/4
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 294 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 132 times.
433 if (shouldthrow && pass)
517 {
518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 asar_throw_error(2, error_type_block, error_id_label_not_found, name.data());
519 }
520 426 rval->pos = (unsigned int)-1;
521 426 rval->freespace_id = 0;
522 426 rval->is_static = false;
523 426 return false;
524 }
525 return true;
526 3652 }
527
528 1792 snes_label labelval(const char ** rawname, bool define)
529 {
530 897 snes_label rval;
531 1792 labelvalcore(rawname, &rval, define, true);
532 1785 return rval;
533 }
534
535 134 snes_label labelval(string name, bool define)
536 {
537 134 const char * rawname=name;
538 68 snes_label rval;
539 134 labelvalcore(&rawname, &rval, define, true);
540 134 return rval;
541 }
542
543 1554 bool labelval(const char ** rawname, snes_label * rval, bool define)
544 {
545 1554 return labelvalcore(rawname, rval, define, false);
546 }
547
548 172 bool labelval(string name, snes_label * rval, bool define)
549 {
550 172 const char * str=name;
551 172 return labelvalcore(&str, rval, define, false);
552 }
553
554 3303 static void setlabel(string name, int loc=-1, bool is_static=false, int freespace_id = -1)
555 {
556
2/2
✓ Branch 0 taken 2811 times.
✓ Branch 1 taken 492 times.
3303 if (loc==-1)
557 {
558 2811 verifysnespos();
559 2811 loc=snespos;
560 }
561
562 1659 snes_label label_data;
563 3303 label_data.pos = (unsigned int)loc;
564 3303 label_data.is_static = is_static;
565
2/2
✓ Branch 0 taken 3297 times.
✓ Branch 1 taken 6 times.
3303 label_data.freespace_id = freespace_id == -1 ? freespaceid : freespace_id;
566
567 unsigned int labelpos;
568
2/2
✓ Branch 0 taken 1105 times.
✓ Branch 1 taken 2198 times.
3303 if (pass==0)
569 {
570
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1099 times.
1105 if (labels.exists(name))
571 {
572 6 movinglabelspossible=true;
573 6 asar_throw_error(0, error_type_block, error_id_label_redefined, name.data());
574 }
575 1099 labels.create(name) = label_data;
576 }
577
2/2
✓ Branch 0 taken 1099 times.
✓ Branch 1 taken 1099 times.
2198 else if (pass==1)
578 {
579 1099 labels.create(name) = label_data;
580 }
581
1/2
✓ Branch 0 taken 1099 times.
✗ Branch 1 not taken.
1099 else if (pass==2)
582 {
583 //all label locations are known at this point, add a sanity check
584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1099 times.
1099 if (!labels.exists(name)) asar_throw_error(2, error_type_block, error_id_label_on_third_pass);
585 1099 labelpos = labels.find(name).pos;
586
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1087 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
1099 if ((int)labelpos != loc && !movinglabelspossible)
587 {
588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if((unsigned int)loc>>16 != labelpos>>16) asar_throw_error(2, error_type_block, error_id_label_ambiguous, name.raw());
589
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 else if(labelpos == (dp_base + 0xFFu)) asar_throw_error(2, error_type_block, error_id_label_ambiguous, name.raw());
590
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 else if(errored) return;
591 else asar_throw_error(2, error_type_block, error_id_label_moving);
592 }
593 }
594 }
595
596 table thetable;
597 static autoarray<table> tablestack;
598
599 2142 static void cleartable()
600 {
601
1/2
✓ Branch 0 taken 2142 times.
✗ Branch 1 not taken.
2142 thetable = table();
602 2142 }
603
604 struct pushable {
605 int arch;
606 int snespos;
607 int snesstart;
608 int snesposreal;
609 int snesstartreal;
610 int freeid;
611 int freest;
612 int arch1;
613 int arch2;
614 int arch3;
615 int arch4;
616 };
617 static autoarray<pushable> pushpc;
618 static int pushpcnum;
619
620 static autoarray<int> basestack;
621 static int basestacknum;
622
623 130 struct ns_pushable {
624 string ns;
625 autoarray<string> namespace_list;
626 bool nested_namespaces;
627 };
628
629 static autoarray<ns_pushable> pushns;
630 static int pushnsnum;
631
632
633 static unsigned char fillbyte[12];
634 static unsigned char padbyte[12];
635
636 static bool nested_namespaces = false;
637
638 4410 static int getfreespaceid()
639 {
640 /*static const int max_num_freespaces = 125;
641 if (freespaceidnext > max_num_freespaces) asar_throw_error(pass, error_type_fatal, error_id_freespace_limit_reached, max_num_freespaces);*/
642 4410 int newid = freespaceidnext++;
643
2/2
✓ Branch 0 taken 1470 times.
✓ Branch 1 taken 2940 times.
4410 if(newid >= freespaces.count) {
644 1470 freespaces[newid].leaked = true;
645 1470 freespaces[newid].orgpos = -2;
646 1470 freespaces[newid].orglen = -1;
647 1470 freespaces[newid].cleanbyte = 0x00;
648 }
649 4410 return newid;
650 }
651
652 133020 void checkbankcross()
653 {
654
2/2
✓ Branch 0 taken 107007 times.
✓ Branch 1 taken 26013 times.
133020 if (!snespos_valid) return;
655
2/2
✓ Branch 0 taken 105873 times.
✓ Branch 1 taken 1134 times.
107007 if (disable_bank_cross_errors) return;
656
2/2
✓ Branch 0 taken 104997 times.
✓ Branch 1 taken 876 times.
105873 unsigned int mask = 0x7FFF0000 | (check_half_banks_crossed ? 0x8000 : 0);
657
4/4
✓ Branch 0 taken 1713 times.
✓ Branch 1 taken 104160 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 1701 times.
105873 if (((snespos^startpos) & mask) && (((snespos - 1) ^ startpos) & mask))
658 {
659 12 asar_throw_error(pass, error_type_fatal, error_id_bank_border_crossed, snespos);
660 }
661 // don't verify realsnespos when using norom. this allows making custom mappers where the file layout doesn't follow bank borders
662
5/6
✓ Branch 0 taken 104985 times.
✓ Branch 1 taken 876 times.
✓ Branch 2 taken 1701 times.
✓ Branch 3 taken 103284 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1701 times.
105861 else if (mapper != norom && ((realsnespos^realstartpos) & mask) && (((realsnespos - 1) ^ realstartpos) & mask))
663 {
664 asar_throw_error(pass, error_type_fatal, error_id_bank_border_crossed, realsnespos);
665 }
666 }
667
668 8886 static void freespaceend()
669 {
670
2/2
✓ Branch 0 taken 4410 times.
✓ Branch 1 taken 4476 times.
8886 if (freespaceid > 0)
671 {
672 4410 freespaces[freespaceid].len = snespos-freespacestart;
673 4410 snespos=(int)0xFFFFFFFF;
674 4410 snespos_valid = false;
675 }
676 8886 freespaceid = 0;
677 8886 }
678
679 int numopcodes;
680
681
1/2
✓ Branch 0 taken 19576 times.
✗ Branch 1 not taken.
19576 static void adddefine(const string & key, string & value)
682 {
683
1/2
✓ Branch 0 taken 19576 times.
✗ Branch 1 not taken.
19576 if (!defines.exists(key)) defines.create(key) = value;
684 19576 }
685
686 2124 void initstuff()
687 {
688
2/2
✓ Branch 0 taken 728 times.
✓ Branch 1 taken 1396 times.
2124 if (pass==0)
689 {
690 728 freespaces.reset();
691 728 movinglabelspossible = false;
692 728 found_rats_tags_initialized = false;
693 728 found_rats_tags.clear();
694 }
695 2124 arch=arch_65816;
696 2124 mapper=lorom;
697 2124 mapper_set = false;
698 2124 calledmacros = 0;
699 2124 reallycalledmacros = 0;
700 2124 macrorecursion = 0;
701 2124 defines.reset();
702 2124 builtindefines.each(adddefine);
703 2124 clidefines.each(adddefine);
704 ns="";
705 2124 namespace_list.reset();
706 2124 sublabels.reset();
707 2124 poslabels.reset();
708 2124 neglabels.reset();
709 2124 macroposlabels = nullptr;
710 2124 macroneglabels = nullptr;
711 2124 macrosublabels = nullptr;
712 2124 cleartable();
713 2124 pushpc.reset();
714 2124 pushpcnum=0;
715 2124 pushns.reset();
716 2124 pushnsnum = 0;
717 2124 bytes=0;
718 2124 freespaceuse=0;
719 2124 memset(fillbyte, 0, sizeof(fillbyte));
720 2124 memset(padbyte, 0, sizeof(padbyte));
721 2124 snespos_valid = false;
722 2124 snespos=(int)0xFFFFFFFF;
723 2124 realsnespos= (int)0xFFFFFFFF;
724 2124 startpos= (int)0xFFFFFFFF;
725 2124 realstartpos= (int)0xFFFFFFFF;
726 //fastrom=false;
727 2124 freespaceidnext=1;
728 2124 freespaceid=0;
729 2124 numopcodes=0;
730 2124 incsrcdepth = 0;
731
732 2124 optimizeforbank = -1;
733 2124 optimize_dp = optimize_dp_flag::NONE;
734 2124 dp_base = 0;
735 2124 optimize_address = optimize_address_flag::DEFAULT;
736
737 2124 in_struct = false;
738 2124 in_sub_struct = false;
739 2124 in_spcblock = false;
740
741
1/2
✓ Branch 0 taken 2124 times.
✗ Branch 1 not taken.
2124 if (arch==arch_65816) asinit_65816();
742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2124 times.
2124 if (arch==arch_spc700) asinit_spc700();
743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2124 times.
2124 if (arch==arch_superfx) asinit_superfx();
744
745 2124 disable_bank_cross_errors = false;
746 2124 check_half_banks_crossed = false;
747 2124 nested_namespaces = false;
748
749 2124 includeonce.reset();
750
751 extern AddressToLineMapping addressToLineMapping;
752 2124 addressToLineMapping.reset();
753
754 2124 push_warnings(false);
755
756 2124 initmathcore();
757
758 2124 callstack.reset();
759 #if defined(_WIN32) || !defined(NO_USE_THREADS)
760 1032 init_stack_use_check();
761 #endif
762 2124 }
763
764 1494 int get_freespace_pin_target(int target_id) {
765 // union-find algorithm
766
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1494 times.
3000 while(freespaces[target_id].pin_target_id != target_id) {
767 // i love programming
768 12 freespaces[target_id].pin_target_id =
769 12 freespaces[freespaces[target_id].pin_target_id].pin_target_id;
770 12 target_id = freespaces[target_id].pin_target_id;
771 }
772 1494 return target_id;
773 }
774
775 698 void resolve_pinned_freespaces() {
776
2/2
✓ Branch 0 taken 1470 times.
✓ Branch 1 taken 698 times.
2168 for(int i = 1; i < freespaces.count; i++)
777 // default to everyone being in a separate component
778 1470 freespaces[i].pin_target_id = i;
779
2/2
✓ Branch 0 taken 1470 times.
✓ Branch 1 taken 698 times.
2168 for(int i = 1; i < freespaces.count; i++) {
780 freespace_data& fs = freespaces[i];
781
2/2
✓ Branch 0 taken 1446 times.
✓ Branch 1 taken 24 times.
1470 if(fs.pin_target == "") continue;
782 12 snes_label value;
783
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
24 if(fs.pin_target_ns && labels.exists(fs.pin_target_ns + fs.pin_target))
784 value = labels.find(fs.pin_target_ns + fs.pin_target);
785
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 else if(labels.exists(fs.pin_target))
786 24 value = labels.find(fs.pin_target);
787 else continue; // the error for this is thrown in the freespace command during pass 2
788 24 fs.pin_target_id = get_freespace_pin_target(value.freespace_id);
789 24 fs.len = 0;
790 }
791 698 }
792
793 698 void allocate_freespaces() {
794 // compute real size of all pinned freespace blocks
795
2/2
✓ Branch 0 taken 1470 times.
✓ Branch 1 taken 698 times.
2168 for(int i = 1; i < freespaces.count; i++) {
796 freespace_data& fs = freespaces[i];
797 // just in case the pin target changed again or something
798 1470 fs.pin_target_id = get_freespace_pin_target(fs.pin_target_id);
799 freespace_data& target = freespaces[fs.pin_target_id];
800 1470 target.total_len += fs.len;
801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1470 times.
1470 target.search_start = std::max(fs.search_start, target.search_start);
802 }
803
804
2/2
✓ Branch 0 taken 1470 times.
✓ Branch 1 taken 698 times.
2168 for(int i = 1; i < freespaces.count; i++) {
805 freespace_data& fs = freespaces[i];
806
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1464 times.
1470 if(fs.dont_find) continue;
807
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1452 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
1464 if(fs.is_static && fs.orgpos > 0) {
808 6 fs.pos = fs.orgpos;
809 6 continue;
810 }
811 // if this freespace is pinned to another one, set it later
812
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1440 times.
1458 if(fs.pin_target_id != i) continue;
813 // TODO: possibly fancier align
814 1440 fs.pos = getsnesfreespace(fs.total_len, fs.bank, true, true, fs.flag_align, fs.cleanbyte, fs.write_rats, fs.search_start);
815 1440 fs.used_len = fs.len;
816 }
817 // set pos for all pinned freespaces
818
2/2
✓ Branch 0 taken 1470 times.
✓ Branch 1 taken 698 times.
2168 for(int i = 1; i < freespaces.count; i++) {
819 freespace_data& fs = freespaces[i];
820
2/2
✓ Branch 0 taken 1452 times.
✓ Branch 1 taken 18 times.
1470 if(fs.pin_target_id == i) continue;
821 freespace_data& tgt = freespaces[fs.pin_target_id];
822 18 fs.pos = tgt.pos + tgt.used_len;
823 18 tgt.used_len += fs.len;
824 }
825
826 // relocate all labels that were in freespace to point them to their real location
827 698 labels.each([](const char * key, snes_label & val) {
828
4/4
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 919 times.
✓ Branch 2 taken 174 times.
✓ Branch 3 taken 6 times.
1279 if(val.freespace_id != 0 && !freespaces[val.freespace_id].dont_find) {
829 174 val.pos += freespaces[val.freespace_id].pos;
830 }
831 1099 });
832 698 }
833
834 //void nerf(const string& left, string& right){puts(S left+" = "+right);}
835
836 2094 void finishpass()
837 {
838 2094 verify_warnings();
839 2094 pull_warnings(false);
840
841 //defines.traverse(nerf);
842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2094 times.
2094 if(in_spcblock) asar_throw_error(0, error_type_block, error_id_missing_endspcblock);
843
2/4
✓ Branch 0 taken 2094 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2094 times.
2094 if (in_struct || in_sub_struct) asar_throw_error(pass, error_type_null, error_id_struct_without_endstruct);
844
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2094 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2094 else if (pushpcnum && pass == 0) asar_throw_error(pass, error_type_null, error_id_pushpc_without_pullpc);
845
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2094 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2094 else if (pushnsnum && pass == 0) asar_throw_error(pass, error_type_null, error_id_pushns_without_pullns);
846 2094 freespaceend();
847
2/2
✓ Branch 0 taken 1968 times.
✓ Branch 1 taken 126 times.
2094 if (arch==arch_65816) asend_65816();
848
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 2004 times.
2094 if (arch==arch_spc700) asend_spc700();
849
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 2058 times.
2094 if (arch==arch_superfx) asend_superfx();
850
851 2094 deinitmathcore();
852
2/2
✓ Branch 0 taken 698 times.
✓ Branch 1 taken 1396 times.
2094 if(pass == 0) {
853 698 resolve_pinned_freespaces();
854
2/2
✓ Branch 0 taken 698 times.
✓ Branch 1 taken 698 times.
1396 } else if(pass == 1) {
855 698 allocate_freespaces();
856 698 handle_cleared_rats_tags();
857 }
858 #if defined(_WIN32) || !defined(NO_USE_THREADS)
859 1017 deinit_stack_use_check();
860 #endif
861 2094 }
862
863 140004 static bool addlabel(const char * label, int pos=-1, bool global_label = false)
864 {
865
3/4
✓ Branch 0 taken 94545 times.
✓ Branch 1 taken 45459 times.
✓ Branch 2 taken 94545 times.
✗ Branch 3 not taken.
140004 if (!label[0] || label[0]==':') return false;//colons are reserved for special labels
866
867 94545 const char* posneglabel = label;
868 94545 string posnegname = posneglabelname(&posneglabel, true);
869
870
2/2
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 94179 times.
94545 if (posnegname.length() > 0)
871 {
872
1/2
✓ Branch 0 taken 366 times.
✗ Branch 1 not taken.
366 if (global_label) return false;
873
3/6
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 294 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 72 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
366 if (*posneglabel != '\0' && *posneglabel != ':') asar_throw_error(0, error_type_block, error_id_broken_label_definition);
874
1/2
✓ Branch 0 taken 366 times.
✗ Branch 1 not taken.
366 setlabel(posnegname, pos);
875 366 return true;
876 }
877
7/8
✓ Branch 0 taken 91755 times.
✓ Branch 1 taken 2424 times.
✓ Branch 2 taken 91572 times.
✓ Branch 3 taken 183 times.
✓ Branch 4 taken 91554 times.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 91554 times.
94179 if (label[strlen(label)-1]==':' || label[0]=='.' || label[0]=='?' || label[0] == '#')
878 {
879
2/2
✓ Branch 0 taken 2589 times.
✓ Branch 1 taken 36 times.
2625 if (!label[1]) return false;
880
6/8
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 2463 times.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 126 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 108 times.
✓ Branch 7 taken 18 times.
2589 if(global_label && (in_struct || in_sub_struct || label[0]=='?')) return false;
881
882 bool define = true;
883
884
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 2499 times.
2571 if (label[0] == '#')
885 {
886 define = false;
887 72 label++;
888 }
889
890 // RPG Hacker: Also checking label[1] now, since it might be a macro sublabel.
891 // Also, apparently this here doesn't account for main labels. I guess because
892 // we don't even get here in the first place if they don't include a colon?
893
6/6
✓ Branch 0 taken 1686 times.
✓ Branch 1 taken 885 times.
✓ Branch 2 taken 1668 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 1650 times.
✓ Branch 5 taken 18 times.
2571 bool requirecolon = (label[0] != '.' && label[1] != '.') && (in_struct || in_sub_struct);
894
2/2
✓ Branch 0 taken 2463 times.
✓ Branch 1 taken 108 times.
2571 string name=labelname(&label, define);
895
2/2
✓ Branch 0 taken 2334 times.
✓ Branch 1 taken 129 times.
2463 if (label[0]==':') label++;
896
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
129 else if (requirecolon) asar_throw_error(0, error_type_block, error_id_broken_label_definition);
897
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 18 times.
129 else if (global_label) return false;
898
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2445 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2445 if (label[0]) asar_throw_error(0, error_type_block, error_id_broken_label_definition);
899
4/4
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 2118 times.
✓ Branch 2 taken 291 times.
✓ Branch 3 taken 36 times.
2736 if (ns && !global_label) name=ns+name;
900
6/6
✓ Branch 0 taken 1887 times.
✓ Branch 1 taken 558 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 1815 times.
✓ Branch 4 taken 2433 times.
✓ Branch 5 taken 12 times.
2445 setlabel(name, pos, ((in_struct || in_sub_struct) && static_struct));
901 2433 return true;
902 2463 }
903 return false;
904 94545 }
905
906 44697 static void add_addr_to_line(int pos)
907 {
908
2/2
✓ Branch 0 taken 15805 times.
✓ Branch 1 taken 28892 times.
44697 if (pass == 2)
909 15805 addressToLineMapping.includeMapping(get_current_file_name(), get_current_line() + 1, pos);
910 44697 }
911
912 static autoarray<bool> elsestatus;
913 int numtrue=0;//if 1 -> increase both
914 int numif = 0; //if 0 or inside if 0 -> increase only numif
915
916 autoarray<whiletracker> whilestatus;
917 int single_line_for_tracker;
918
919
920 270 static void push_pc()
921 {
922 270 pushpc[pushpcnum].arch=arch;
923 270 pushpc[pushpcnum].snespos=snespos;
924 270 pushpc[pushpcnum].snesstart=startpos;
925 270 pushpc[pushpcnum].snesposreal=realsnespos;
926 270 pushpc[pushpcnum].snesstartreal=realstartpos;
927 270 pushpc[pushpcnum].freeid=freespaceid;
928 270 pushpc[pushpcnum].freest=freespacestart;
929 270 pushpcnum++;
930 270 }
931
932 270 static void pop_pc()
933 {
934 270 pushpcnum--;
935 270 snespos=pushpc[pushpcnum].snespos;
936 270 startpos=pushpc[pushpcnum].snesstart;
937 270 realsnespos=pushpc[pushpcnum].snesposreal;
938 270 realstartpos=pushpc[pushpcnum].snesstartreal;
939 270 freespaceid=pushpc[pushpcnum].freeid;
940 270 freespacestart=pushpc[pushpcnum].freest;
941 270 }
942
943
944 984 string handle_print(char* input)
945 {
946 498 string out;
947
1/2
✓ Branch 0 taken 984 times.
✗ Branch 1 not taken.
984 autoptr<char**> pars = qpsplit(input, ',');
948
1/2
✓ Branch 0 taken 984 times.
✗ Branch 1 not taken.
984 verify_paren(pars);
949
2/2
✓ Branch 0 taken 1659 times.
✓ Branch 1 taken 966 times.
2625 for (int i = 0; pars[i]; i++)
950 {
951 if (0);
952
3/4
✓ Branch 0 taken 1218 times.
✓ Branch 1 taken 441 times.
✓ Branch 2 taken 1218 times.
✗ Branch 3 not taken.
1659 else if (pars[i][0] == '"') out += safedequote(pars[i]);
953
4/4
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 207 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 198 times.
441 else if (!stricmp(pars[i], "bytes")) out += dec(bytes);
954
4/4
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 198 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 189 times.
405 else if (!stricmp(pars[i], "freespaceuse")) out += dec(freespaceuse);
955
3/4
✓ Branch 0 taken 189 times.
✓ Branch 1 taken 198 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 189 times.
387 else if (!stricmp(pars[i], "pc")) out += hex((unsigned int)(snespos & 0xFFFFFF), 6);
956
3/4
✓ Branch 0 taken 189 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
✓ Branch 3 taken 36 times.
684 else if (!strncasecmp(pars[i], "bin(", strlen("bin(")) ||
957
4/4
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 36 times.
405 !strncasecmp(pars[i], "dec(", strlen("dec(")) ||
958
6/6
✓ Branch 0 taken 297 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 180 times.
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 63 times.
✓ Branch 5 taken 9 times.
681 !strncasecmp(pars[i], "hex(", strlen("hex(")) ||
959
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 9 times.
144 !strncasecmp(pars[i], "double(", strlen("double(")))
960 {
961 369 char * arg1pos = strchr(pars[i], '(') + 1;
962 180 char * endpos = strchr(arg1pos, '\0');
963
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 738 times.
✓ Branch 2 taken 369 times.
✓ Branch 3 taken 369 times.
738 while (*endpos == ' ' || *endpos == '\0') endpos--;
964
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 369 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
369 if (*endpos != ')') asar_throw_error(0, error_type_block, error_id_invalid_print_function_syntax);
965 369 string paramstr = string(arg1pos, (int)(endpos - arg1pos));
966
967 int numargs;
968
1/2
✓ Branch 0 taken 369 times.
✗ Branch 1 not taken.
369 autoptr<char**> params = qpsplit(paramstr.temp_raw(), ',', &numargs);
969
1/2
✓ Branch 0 taken 369 times.
✗ Branch 1 not taken.
369 verify_paren(params);
970
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 369 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
369 if (numargs > 2) asar_throw_error(0, error_type_block, error_id_wrong_num_parameters);
971 int precision = 0;
972 369 bool hasprec = numargs == 2;
973
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 234 times.
369 if (hasprec)
974 {
975
1/2
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
234 precision = getnum(params[1]);
976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 234 times.
234 if (precision < 0) precision = 0;
977 234 if (precision > 64) precision = 64;
978 }
979 369 *(arg1pos - 1) = '\0'; // allows more convenient comparsion functions
980
4/4
✓ Branch 0 taken 225 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 135 times.
369 if (!stricmp(pars[i], "bin"))
981 {
982 // sadly printf doesn't have binary, so let's roll our own
983
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 int64_t value = getnum(params[0]);
984 char buffer[65];
985
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 72 times.
90 if (value < 0) {
986 18 out += '-';
987 18 value = -value;
988 // decrement precision because we've output one char already
989 18 precision -= 1;
990
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (precision<0) precision = 0;
991 }
992
2/2
✓ Branch 0 taken 5760 times.
✓ Branch 1 taken 90 times.
5850 for (int j = 0; j < 64; j++) {
993 5760 buffer[63 - j] = '0' + ((value & (1ull << j)) >> j);
994 }
995 90 buffer[64] = 0;
996 int startidx = 0;
997
4/4
✓ Branch 0 taken 5184 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 5166 times.
✓ Branch 3 taken 18 times.
5256 while (startidx < 64 - precision && buffer[startidx] == '0') startidx++;
998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 if (startidx == 64) startidx--; // always want to print at least one digit
999 90 out += buffer + startidx;
1000 }
1001
4/4
✓ Branch 0 taken 174 times.
✓ Branch 1 taken 105 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 99 times.
279 else if (!stricmp(pars[i], "dec"))
1002 {
1003
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 int64_t value = getnum(params[0]);
1004 char buffer[65];
1005
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
75 snprintf(buffer, 65, "%0*" PRId64, precision, value);
1006 75 out += buffer;
1007 }
1008
4/4
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 63 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 63 times.
204 else if (!stricmp(pars[i], "hex"))
1009 {
1010
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 int64_t value = getnum(params[0]);
1011 char buffer[65];
1012
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
78 snprintf(buffer, 65, "%0*" PRIX64, precision, value);
1013 78 out += buffer;
1014 }
1015
2/4
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
126 else if (!stricmp(pars[i], "double"))
1016 {
1017
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 18 times.
126 if (!hasprec) precision = 5;
1018
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 out += ftostrvar(getnumdouble(params[0]), precision);
1019 }
1020 369 }
1021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 else asar_throw_error(2, error_type_block, error_id_unknown_variable);
1022 }
1023 966 return out;
1024 1002 }
1025
1026 // single_line_for_tracker is:
1027 // 0 if not in first block of line, not in (single-line) for loop
1028 // 1 if first block of line
1029 // 2 if in single-line for loop
1030 // 3 if after endfor (of a single-line loop)
1031 150426 void assembleblock(const char * block, int& single_line_for_tracker)
1032 {
1033 #define is(test) (!stricmpwithlower(word[0], test))
1034 #define is0(test) (numwords==1 && !stricmpwithlower(word[0], test))
1035 #define is1(test) (numwords==2 && !stricmpwithlower(word[0], test))
1036 #define is2(test) (numwords==3 && !stricmpwithlower(word[0], test))
1037 #define is3(test) (numwords==4 && !stricmpwithlower(word[0], test))
1038 #define par word[1]
1039
1040 68565 callstack_push cs_push(callstack_entry_type::BLOCK, block);
1041
1042 int numwords;
1043 68565 string splitblock = block;
1044
1/2
✓ Branch 0 taken 150426 times.
✗ Branch 1 not taken.
150426 char ** word = qsplit(splitblock.temp_raw(), ' ', &numwords);
1045 autoptr<char **> scope_word = word;
1046 // when writing out the data for the addrToLine mapping,
1047 // we want to write out the snespos we had before writing opcodes
1048 150426 int addrToLinePos = realsnespos & 0xFFFFFF;
1049
1050
12/12
✓ Branch 0 taken 143451 times.
✓ Branch 1 taken 9684 times.
✓ Branch 2 taken 141318 times.
✓ Branch 3 taken 2133 times.
✓ Branch 4 taken 79011 times.
✓ Branch 5 taken 62307 times.
✓ Branch 6 taken 77571 times.
✓ Branch 7 taken 1440 times.
✓ Branch 8 taken 139758 times.
✓ Branch 9 taken 120 times.
✓ Branch 10 taken 2709 times.
✓ Branch 11 taken 137049 times.
153135 while (numif==numtrue && word[0] && (!word[1] || strcmp(word[1], "=")) && addlabel(word[0]))
1051 {
1052 2709 word++;
1053 2709 numwords--;
1054 }
1055
4/4
✓ Branch 0 taken 148173 times.
✓ Branch 1 taken 2133 times.
✓ Branch 2 taken 101922 times.
✓ Branch 3 taken 46251 times.
150306 if (!word[0] || !word[0][0]) return;
1056
10/10
✓ Branch 0 taken 100278 times.
✓ Branch 1 taken 1644 times.
✓ Branch 2 taken 99288 times.
✓ Branch 3 taken 990 times.
✓ Branch 4 taken 99198 times.
✓ Branch 5 taken 90 times.
✓ Branch 6 taken 93420 times.
✓ Branch 7 taken 5778 times.
✓ Branch 8 taken 92376 times.
✓ Branch 9 taken 1044 times.
101922 if (is("if") || is("elseif") || is("assert") || is("while") || is("for"))
1057 {
1058 4773 string errmsg;
1059 4773 whiletracker wstatus;
1060
1/2
✓ Branch 0 taken 9546 times.
✗ Branch 1 not taken.
9546 wstatus.startline = get_current_line();
1061 9546 wstatus.iswhile = is("while");
1062 9546 wstatus.cond = false;
1063 9546 wstatus.is_for = false;
1064 9546 wstatus.for_start = wstatus.for_end = wstatus.for_cur = 0;
1065 9546 wstatus.for_has_var_backup = false;
1066
2/2
✓ Branch 0 taken 1044 times.
✓ Branch 1 taken 8502 times.
9546 if(is("for")) wstatus.is_for = true;
1067
1068 bool is_for_cont = false;
1069 // if this is a for loop and a whilestatus entry already exists at this level,
1070 // and the for loop isn't finished, this is a continuation of the for loop
1071
4/4
✓ Branch 0 taken 1042 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 996 times.
✓ Branch 3 taken 46 times.
2086 if (is("for") && whilestatus.count > numif && whilestatus[numif].is_for
1072
4/4
✓ Branch 0 taken 1044 times.
✓ Branch 1 taken 8502 times.
✓ Branch 2 taken 258 times.
✓ Branch 3 taken 738 times.
10542 && whilestatus[numif].for_cur < whilestatus[numif].for_end)
1073 is_for_cont = true;
1074 9546 whiletracker& addedwstatus = is_for_cont ? whilestatus[numif] : (whilestatus[numif] = wstatus);
1075
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 9456 times.
9546 if (is("assert"))
1076 {
1077
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 autoptr<char**> tokens = qpsplit(word[numwords - 1], ',');
1078
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 verify_paren(tokens);
1079
3/4
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 54 times.
90 if (tokens[0] != NULL && tokens[1] != NULL)
1080 {
1081 18 string rawerrmsg;
1082 size_t pos = 1;
1083
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 36 times.
162 while (tokens[pos])
1084 {
1085 126 rawerrmsg += tokens[pos];
1086
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 36 times.
126 if (tokens[pos + 1] != NULL)
1087 {
1088 90 rawerrmsg += ",";
1089 }
1090 pos++;
1091 }
1092
1093
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 errmsg = handle_print(rawerrmsg.raw());
1094 36 }
1095 90 }
1096
1097 //handle nested if statements
1098
6/6
✓ Branch 0 taken 1008 times.
✓ Branch 1 taken 8538 times.
✓ Branch 2 taken 666 times.
✓ Branch 3 taken 342 times.
✓ Branch 4 taken 522 times.
✓ Branch 5 taken 144 times.
9546 if (numtrue!=numif && !(is("elseif") && numtrue+1==numif))
1099 {
1100
6/6
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 198 times.
✓ Branch 3 taken 144 times.
✓ Branch 4 taken 54 times.
✓ Branch 5 taken 144 times.
486 if ((is("if") || is("while") || is("for"))) numif++;
1101 return;
1102 }
1103
6/6
✓ Branch 0 taken 7560 times.
✓ Branch 1 taken 1500 times.
✓ Branch 2 taken 1926 times.
✓ Branch 3 taken 5634 times.
✓ Branch 4 taken 990 times.
✓ Branch 5 taken 936 times.
9060 if ((is("if") || is("while") || is("for"))) numif++;
1104
1105
2/2
✓ Branch 0 taken 15912 times.
✓ Branch 1 taken 9060 times.
24972 for(int i = 1; i < numwords - 1; i++)
1106 {
1107 15912 word[i][strlen(word[i])] = ' ';
1108 }
1109 9060 numwords = 2;
1110
1111 bool cond;
1112
2/2
✓ Branch 0 taken 8070 times.
✓ Branch 1 taken 990 times.
9060 if(!is("for"))
1113 {
1114
1/2
✓ Branch 0 taken 8070 times.
✗ Branch 1 not taken.
8070 cond = getnum(word[1]);
1115
6/8
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 7890 times.
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 90 times.
✓ Branch 4 taken 90 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 90 times.
8070 if (foundlabel && !foundlabel_static && !is("assert")) asar_throw_error(1, error_type_block, error_id_label_in_conditional, word[0]);
1116 }
1117
1118
2/2
✓ Branch 0 taken 990 times.
✓ Branch 1 taken 7980 times.
8970 if (is("for"))
1119 {
1120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 990 times.
990 if(single_line_for_tracker != 1)
1121 {
1122 numif--;
1123 asar_throw_error(0, error_type_line, error_id_bad_single_line_for);
1124 }
1125
1126
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 738 times.
990 if(!is_for_cont)
1127 {
1128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
252 char* past_eq = strchr(word[1], '=');
1129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 252 times.
252 if(!past_eq)
1130 asar_throw_error(0, error_type_block, error_id_broken_for_loop, "missing loop range");
1131
1132 252 string varname(word[1], past_eq - word[1]);
1133 252 past_eq += 1;
1134 252 strip_whitespace(varname);
1135
2/4
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 252 times.
252 if(!validatedefinename(varname))
1136 asar_throw_error(0, error_type_block, error_id_broken_for_loop, "invalid define name");
1137
1138
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
252 char* range_sep = strqpstr(past_eq, "..");
1139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 252 times.
252 if(!range_sep)
1140 asar_throw_error(0, error_type_block, error_id_broken_for_loop, "invalid loop range");
1141
1142 252 string for_start(past_eq, range_sep - past_eq);
1143 252 strip_whitespace(for_start);
1144 252 string for_end(range_sep+2);
1145 252 strip_whitespace(for_end);
1146
1147
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
252 addedwstatus.for_start = getnum(for_start);
1148
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 252 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
252 if(foundlabel && !foundlabel_static)
1149 asar_throw_error(0, error_type_block, error_id_label_in_conditional, "for");
1150
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
252 addedwstatus.for_end = getnum(for_end);
1151
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 252 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
252 if(foundlabel && !foundlabel_static)
1152 asar_throw_error(0, error_type_block, error_id_label_in_conditional, "for");
1153
1154 252 addedwstatus.for_variable = varname;
1155 252 addedwstatus.for_cur = addedwstatus.for_start;
1156 252 }
1157 738 else addedwstatus.for_cur++;
1158
1159 990 addedwstatus.cond = addedwstatus.for_cur < addedwstatus.for_end;
1160 990 single_line_for_tracker = 2;
1161
2/2
✓ Branch 0 taken 738 times.
✓ Branch 1 taken 252 times.
990 if(addedwstatus.cond)
1162 {
1163
2/2
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 162 times.
738 numtrue++;
1164
2/2
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 162 times.
738 if(defines.exists(addedwstatus.for_variable))
1165 {
1166 576 addedwstatus.for_has_var_backup = true;
1167 576 addedwstatus.for_var_backup = defines.find(addedwstatus.for_variable);
1168 }
1169
1/2
✓ Branch 0 taken 738 times.
✗ Branch 1 not taken.
738 defines.create(addedwstatus.for_variable) = ftostr(addedwstatus.for_cur);
1170 }
1171 }
1172
4/4
✓ Branch 0 taken 6570 times.
✓ Branch 1 taken 1410 times.
✓ Branch 2 taken 936 times.
✓ Branch 3 taken 5634 times.
7980 else if (is("if") || is("while"))
1173 {
1174 if(0);
1175
2/2
✓ Branch 0 taken 5754 times.
✓ Branch 1 taken 1290 times.
7044 else if (cond)
1176 {
1177 5754 numtrue++;
1178 5754 elsestatus[numif]=true;
1179 }
1180 else if (!cond)
1181 {
1182 1290 elsestatus[numif]=false;
1183 }
1184 7044 addedwstatus.cond = cond;
1185 }
1186
2/2
✓ Branch 0 taken 846 times.
✓ Branch 1 taken 90 times.
936 else if (is("elseif"))
1187 {
1188
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 846 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
846 if (!numif) asar_throw_error(1, error_type_block, error_id_misplaced_elseif);
1189
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 846 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
846 if (whilestatus[numif - 1].iswhile) asar_throw_error(1, error_type_block, error_id_elseif_in_while);
1190
2/2
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 522 times.
846 if (numif==numtrue) numtrue--;
1191
4/4
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 522 times.
✓ Branch 2 taken 234 times.
✓ Branch 3 taken 90 times.
1170 if (cond && !elsestatus[numif])
1192 {
1193 234 numtrue++;
1194 234 elsestatus[numif]=true;
1195 }
1196 }
1197 // otherwise, must be assert command
1198
4/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 6 times.
90 else if (pass == 2 && !cond)
1199 {
1200
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
48 if (errmsg) asar_throw_error(2, error_type_block, error_id_assertion_failed, (string(": ") + errmsg).data());
1201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 else asar_throw_error(2, error_type_block, error_id_assertion_failed, ".");
1202 }
1203 9660 }
1204
12/12
✓ Branch 0 taken 18423 times.
✓ Branch 1 taken 73953 times.
✓ Branch 2 taken 16779 times.
✓ Branch 3 taken 1644 times.
✓ Branch 4 taken 16779 times.
✓ Branch 5 taken 73953 times.
✓ Branch 6 taken 11001 times.
✓ Branch 7 taken 5778 times.
✓ Branch 8 taken 11001 times.
✓ Branch 9 taken 73953 times.
✓ Branch 10 taken 1044 times.
✓ Branch 11 taken 9957 times.
92376 else if (is0("endif") || is0("endwhile") || is0("endfor"))
1205 {
1206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8466 times.
8466 if (!numif)
1207 asar_throw_error(1, error_type_block, error_id_misplaced_endif);
1208 8466 whiletracker& thisws = whilestatus[numif - 1];
1209
1210
3/4
✓ Branch 0 taken 1644 times.
✓ Branch 1 taken 5778 times.
✓ Branch 2 taken 1644 times.
✗ Branch 3 not taken.
7422 if((!thisws.is_for && !thisws.iswhile && !is("endif")) ||
1211
7/8
✓ Branch 0 taken 7422 times.
✓ Branch 1 taken 1044 times.
✓ Branch 2 taken 5778 times.
✓ Branch 3 taken 2688 times.
✓ Branch 4 taken 5778 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1044 times.
✓ Branch 7 taken 7422 times.
15888 (thisws.iswhile && !is("endwhile")) ||
1212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1044 times.
1044 (thisws.is_for && !is("endfor")))
1213 asar_throw_error(1, error_type_block, error_id_misplaced_endif);
1214
1215
2/2
✓ Branch 0 taken 6258 times.
✓ Branch 1 taken 2208 times.
8466 if (numif==numtrue) numtrue--;
1216 8466 numif--;
1217
1218
2/2
✓ Branch 0 taken 1044 times.
✓ Branch 1 taken 7422 times.
8466 if(thisws.is_for)
1219 {
1220
2/2
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 864 times.
1044 if(single_line_for_tracker == 2) single_line_for_tracker = 3;
1221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1044 times.
1044 if(moreonline)
1222 {
1223 // sabotage the whilestatus to prevent the loop running again
1224 // and spamming more of the same error
1225 thisws.for_cur = thisws.for_end;
1226 thisws.cond = false;
1227 asar_throw_error(0, error_type_block, error_id_bad_single_line_for);
1228 }
1229
1230
2/2
✓ Branch 0 taken 738 times.
✓ Branch 1 taken 306 times.
1044 if(thisws.cond)
1231 {
1232
2/2
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 162 times.
738 if(thisws.for_has_var_backup)
1233
1/2
✓ Branch 0 taken 576 times.
✗ Branch 1 not taken.
576 defines.create(thisws.for_variable) = thisws.for_var_backup;
1234 else
1235
1/2
✓ Branch 0 taken 162 times.
✗ Branch 1 not taken.
162 defines.remove(thisws.for_variable);
1236 }
1237 }
1238 }
1239
4/4
✓ Branch 0 taken 9957 times.
✓ Branch 1 taken 73953 times.
✓ Branch 2 taken 9159 times.
✓ Branch 3 taken 798 times.
83910 else if (is0("else"))
1240 {
1241
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 798 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
798 if (!numif) asar_throw_error(1, error_type_block, error_id_misplaced_else);
1242
2/6
✓ Branch 0 taken 798 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 798 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
798 if (whilestatus[numif - 1].iswhile || whilestatus[numif - 1].is_for) asar_throw_error(1, error_type_block, error_id_else_in_while_loop);
1243
2/2
✓ Branch 0 taken 318 times.
✓ Branch 1 taken 480 times.
798 else if (numif==numtrue) numtrue--;
1244
4/4
✓ Branch 0 taken 444 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 174 times.
✓ Branch 3 taken 270 times.
924 else if (numif==numtrue+1 && !elsestatus[numif])
1245 {
1246 174 numtrue++;
1247 174 elsestatus[numif]=true;
1248 }
1249 }
1250
2/2
✓ Branch 0 taken 77916 times.
✓ Branch 1 taken 5196 times.
83112 else if (numif!=numtrue) return;
1251
4/4
✓ Branch 0 taken 77886 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 28977 times.
✓ Branch 3 taken 48909 times.
77916 else if (asblock_pick(word, numwords))
1252 {
1253
1/2
✓ Branch 0 taken 28977 times.
✗ Branch 1 not taken.
28977 add_addr_to_line(addrToLinePos);
1254 28977 numopcodes += recent_opcode_num;
1255 }
1256
10/10
✓ Branch 0 taken 45462 times.
✓ Branch 1 taken 3447 times.
✓ Branch 2 taken 33864 times.
✓ Branch 3 taken 11598 times.
✓ Branch 4 taken 33720 times.
✓ Branch 5 taken 144 times.
✓ Branch 6 taken 31932 times.
✓ Branch 7 taken 1788 times.
✓ Branch 8 taken 288 times.
✓ Branch 9 taken 31644 times.
48909 else if (numwords > 1 && (is("db") || is("dw") || is("dl") || is("dd")))
1257 {
1258 6930 string line;
1259
2/2
✓ Branch 0 taken 13818 times.
✓ Branch 1 taken 13818 times.
27636 for(int i = 1; i < numwords; i++){
1260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13818 times.
13818 if(i > 1) line += " ";
1261 13818 line += word[i];
1262 }
1263
1/2
✓ Branch 0 taken 13818 times.
✗ Branch 1 not taken.
13818 autoptr<char**> pars=qpsplit(line.temp_raw(), ',');
1264
1/2
✓ Branch 0 taken 13818 times.
✗ Branch 1 not taken.
13818 verify_paren(pars);
1265
1266 void (*do_write)(unsigned int);
1267 13818 char first = to_lower(word[0][1]);
1268
2/2
✓ Branch 0 taken 2220 times.
✓ Branch 1 taken 11598 times.
13818 if (first == 'b') do_write = &write1;
1269
2/2
✓ Branch 0 taken 2076 times.
✓ Branch 1 taken 144 times.
2220 else if (first == 'w') do_write = &write2;
1270
2/2
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 1788 times.
2076 else if (first == 'l') do_write = &write3;
1271 else do_write = &write4;
1272
1273
2/2
✓ Branch 0 taken 16308 times.
✓ Branch 1 taken 13752 times.
30060 for (int i=0;pars[i];i++)
1274 {
1275
2/2
✓ Branch 0 taken 669 times.
✓ Branch 1 taken 15639 times.
16308 if (pars[i][0]=='"')
1276 {
1277
1/2
✓ Branch 0 taken 669 times.
✗ Branch 1 not taken.
669 char * str=const_cast<char*>(safedequote(pars[i]));
1278 669 int codepoint = 0u;
1279
1/2
✓ Branch 0 taken 669 times.
✗ Branch 1 not taken.
669 str += utf8_val(&codepoint, str);
1280
2/2
✓ Branch 0 taken 2718 times.
✓ Branch 1 taken 669 times.
3387 while ( codepoint != 0 && codepoint != -1 )
1281 {
1282
2/4
✓ Branch 0 taken 2718 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2718 times.
✗ Branch 3 not taken.
2718 do_write(thetable.get_val(codepoint));
1283
1/2
✓ Branch 0 taken 2718 times.
✗ Branch 1 not taken.
2718 str += utf8_val(&codepoint, str);
1284 }
1285
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 669 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
669 if (codepoint == -1) asar_throw_error(0, error_type_block, error_id_invalid_utf8);
1286 }
1287 else
1288 {
1289
5/6
✓ Branch 0 taken 5207 times.
✓ Branch 1 taken 10432 times.
✓ Branch 2 taken 5141 times.
✓ Branch 3 taken 66 times.
✓ Branch 4 taken 15573 times.
✗ Branch 5 not taken.
15639 do_write((pass==2)?getnum(pars[i]):0);
1290 }
1291 }
1292
1/2
✓ Branch 0 taken 13752 times.
✗ Branch 1 not taken.
13752 add_addr_to_line(addrToLinePos);
1293 13884 }
1294
2/2
✓ Branch 0 taken 1566 times.
✓ Branch 1 taken 33525 times.
35091 else if(word[0][0]=='%')
1295 {
1296
2/2
✓ Branch 0 taken 1530 times.
✓ Branch 1 taken 36 times.
1566 callmacro(strchr(block, '%')+1);
1297 }
1298
4/4
✓ Branch 0 taken 28968 times.
✓ Branch 1 taken 4557 times.
✓ Branch 2 taken 28608 times.
✓ Branch 3 taken 360 times.
33525 else if (is1("undef"))
1299 {
1300
1/2
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
360 string def = safedequote(par);
1301
1302
2/2
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 18 times.
360 if (defines.exists(def))
1303 {
1304
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 defines.remove(def);
1305 }
1306 else
1307 {
1308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 asar_throw_error(0, error_type_block, error_id_define_not_found, def.data());
1309 }
1310 360 }
1311
4/4
✓ Branch 0 taken 1899 times.
✓ Branch 1 taken 31266 times.
✓ Branch 2 taken 1881 times.
✓ Branch 3 taken 18 times.
33165 else if (is0("error"))
1312 {
1313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 asar_throw_error(0, error_type_block, error_id_error_command, ".");
1314 }
1315
4/4
✓ Branch 0 taken 1881 times.
✓ Branch 1 taken 31266 times.
✓ Branch 2 taken 1863 times.
✓ Branch 3 taken 18 times.
33147 else if (is0("warn"))
1316 {
1317
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 asar_throw_warning(2, warning_id_warn_command, ".");
1318 }
1319
4/4
✓ Branch 0 taken 28608 times.
✓ Branch 1 taken 4521 times.
✓ Branch 2 taken 28569 times.
✓ Branch 3 taken 39 times.
33129 else if (is1("error"))
1320 {
1321
1/2
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
39 string out = handle_print(par);
1322 // RPG Hacker: This used to be on pass 0, which had its merits (you don't want to miss a potentially critical
1323 // user-generated error, just because a bazillion other errors are thrown in passes before it). However, I
1324 // don't see how to support print functions with this without moving it to pass 2. Suggestions are welcome.
1325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
99 asar_throw_error(2, error_type_block, error_id_error_command, (string(": ") + out).data());
1326 39 }
1327
4/4
✓ Branch 0 taken 28569 times.
✓ Branch 1 taken 4521 times.
✓ Branch 2 taken 28530 times.
✓ Branch 3 taken 39 times.
33090 else if (is1("warn"))
1328 {
1329
1/2
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
39 string out = handle_print(par);
1330
1/2
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
60 asar_throw_warning(2, warning_id_warn_command, (string(": ") + out).data());
1331 39 }
1332
4/4
✓ Branch 0 taken 28530 times.
✓ Branch 1 taken 4521 times.
✓ Branch 2 taken 28386 times.
✓ Branch 3 taken 144 times.
33051 else if (is1("warnings"))
1333 {
1334
4/4
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 36 times.
144 if (stricmp(word[1], "push") == 0)
1335 {
1336
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 push_warnings();
1337 }
1338
2/4
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
72 else if (stricmp(word[1], "pull") == 0)
1339 {
1340
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 18 times.
72 pull_warnings();
1341 }
1342 else
1343 {
1344 asar_throw_error(0, error_type_block, error_id_broken_command, "warnings", "Unknown parameter");
1345 }
1346 }
1347
4/4
✓ Branch 0 taken 2442 times.
✓ Branch 1 taken 30465 times.
✓ Branch 2 taken 2190 times.
✓ Branch 3 taken 252 times.
32907 else if (is2("warnings"))
1348 {
1349
4/4
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 99 times.
252 if (stricmp(word[1], "enable") == 0)
1350 {
1351
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 asar_warning_id warnid = parse_warning_id_from_string(word[2]);
1352
1353
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 18 times.
54 if (warnid != warning_id_end)
1354 {
1355
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 set_warning_enabled(warnid, true);
1356 }
1357 else
1358 {
1359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 asar_throw_error(0, error_type_block, error_id_invalid_warning_id, word[2], "warnings enable");
1360 }
1361 }
1362
2/4
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
✗ Branch 3 not taken.
198 else if (stricmp(word[1], "disable") == 0)
1363 {
1364
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 asar_warning_id warnid = parse_warning_id_from_string(word[2]);
1365
1366
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 36 times.
198 if (warnid != warning_id_end)
1367 {
1368
1/2
✓ Branch 0 taken 162 times.
✗ Branch 1 not taken.
162 set_warning_enabled(warnid, false);
1369 }
1370 else
1371 {
1372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 asar_throw_error(0, error_type_block, error_id_invalid_warning_id, word[2], "warnings disable");
1373 }
1374 }
1375 else
1376 {
1377 asar_throw_error(0, error_type_block, error_id_broken_command, "warnings", "Unknown parameter");
1378 }
1379 }
1380
4/4
✓ Branch 0 taken 28386 times.
✓ Branch 1 taken 4269 times.
✓ Branch 2 taken 28260 times.
✓ Branch 3 taken 126 times.
32655 else if(is1("global"))
1381 {
1382
3/4
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 90 times.
126 if (!addlabel(word[1], -1, true))
1383 {
1384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 asar_throw_error(1, error_type_block, error_id_invalid_global_label, word[1]);
1385 }
1386 }
1387
4/4
✓ Branch 0 taken 2190 times.
✓ Branch 1 taken 30339 times.
✓ Branch 2 taken 1980 times.
✓ Branch 3 taken 210 times.
32529 else if (is2("check"))
1388 {
1389
4/4
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 96 times.
210 if (stricmp(word[1], "title") == 0)
1390 {
1391 // RPG Hacker: Removed trimming for now - I think requiring an exact match is probably
1392 // better here (not sure, though, it's worth discussing)
1393
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 string expected_title = safedequote(word[2]);
1394 // randomdude999: this also removes leading spaces because itrim gets stuck in an endless
1395 // loop when multi is true and one argument is empty
1396 // in hirom the rom needs to be an entire bank for it to have a title, other modes only need 0x8000 bytes
1397
3/6
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
18 if (romlen < ((mapper == hirom || mapper == exhirom) ? 0x10000 : 0x8000)) // too short
1398 {
1399 if (!ignoretitleerrors) // title errors shouldn't be ignored
1400 asar_throw_error(0, error_type_block, error_id_rom_too_short, expected_title.data());
1401 else // title errors should be ignored, throw a warning anyways
1402 asar_throw_warning(0, warning_id_rom_too_short, expected_title.data());
1403 }
1404 else {
1405 9 string actual_title;
1406 9 string actual_display_title;
1407
2/2
✓ Branch 0 taken 378 times.
✓ Branch 1 taken 18 times.
396 for (int i = 0;i < 21;i++)
1408 {
1409
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
378 unsigned char c = romdata[snestopc(0x00FFC0 + i)];
1410 378 actual_title += (char)c;
1411 // the replacements are from interface-cli.cpp
1412
1/2
✓ Branch 0 taken 378 times.
✗ Branch 1 not taken.
378 if (c == 7) c = 14;
1413
1/2
✓ Branch 0 taken 378 times.
✗ Branch 1 not taken.
378 if (c == 8) c = 27;
1414
1/2
✓ Branch 0 taken 378 times.
✗ Branch 1 not taken.
378 if (c == 9) c = 26;
1415
1/2
✓ Branch 0 taken 378 times.
✗ Branch 1 not taken.
378 if (c == '\r') c = 17;
1416
1/2
✓ Branch 0 taken 378 times.
✗ Branch 1 not taken.
378 if (c == '\n') c = 25;
1417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 378 times.
378 if (c == '\0') c = 155;
1418 378 actual_display_title += (char)c;
1419 }
1420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (strncmp(expected_title, actual_title, 21) != 0)
1421 {
1422 if (!ignoretitleerrors) // title errors shouldn't be ignored
1423 asar_throw_error(0, error_type_block, error_id_rom_title_incorrect, expected_title.data(), actual_display_title.data());
1424 else // title errors should be ignored, throw a warning anyways
1425 asar_throw_warning(0, warning_id_rom_title_incorrect, expected_title.data(), actual_display_title.data());
1426 }
1427 18 }
1428 18 }
1429
2/4
✓ Branch 0 taken 192 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
192 else if (stricmp(word[1], "bankcross") == 0)
1430 {
1431 if (0);
1432
4/4
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 51 times.
192 else if (!stricmp(word[2], "off"))
1433 {
1434 90 disable_bank_cross_errors = true;
1435 }
1436
4/4
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 3 times.
102 else if (!stricmp(word[2], "half"))
1437 {
1438 96 disable_bank_cross_errors = false;
1439 96 check_half_banks_crossed = true;
1440 }
1441
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 else if (!stricmp(word[2], "full"))
1442 {
1443 6 disable_bank_cross_errors = false;
1444 6 check_half_banks_crossed = false;
1445 }
1446 else asar_throw_error(0, error_type_block, error_id_invalid_check);
1447
1448 }
1449 else
1450 {
1451 asar_throw_error(0, error_type_block, error_id_invalid_check);
1452 }
1453 }
1454
7/8
✓ Branch 0 taken 1863 times.
✓ Branch 1 taken 30456 times.
✓ Branch 2 taken 1863 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28260 times.
✓ Branch 5 taken 4059 times.
✓ Branch 6 taken 108 times.
✓ Branch 7 taken 28152 times.
32319 else if (is0("asar") || is1("asar"))
1455 {
1456
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
108 if (!asarverallowed) asar_throw_error(0, error_type_block, error_id_start_of_file);
1457
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
198 if (!par) return;
1458 int dots=0;
1459 int dig=0;
1460
2/2
✓ Branch 0 taken 450 times.
✓ Branch 1 taken 108 times.
558 for (int i=0;par[i];i++)
1461 {
1462
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 324 times.
450 if (par[i]=='.')
1463 {
1464
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
126 if (!dig) asar_throw_error(0, error_type_block, error_id_invalid_version_number);
1465 dig=0;
1466 126 dots++;
1467 }
1468
1/2
✓ Branch 0 taken 324 times.
✗ Branch 1 not taken.
324 else if (is_digit(par[i])) dig++;
1469 else asar_throw_error(0, error_type_block, error_id_invalid_version_number);
1470 }
1471
2/6
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 108 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
108 if (!dig || !dots || dots>2) asar_throw_error(0, error_type_block, error_id_invalid_version_number);
1472
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 autoptr<char**> vers=split(par, '.');
1473 108 int vermaj=atoi(vers[0]);
1474
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
108 if (vermaj > asarver_maj) asar_throw_error(pass, error_type_fatal, error_id_asar_too_old);
1475
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 18 times.
108 if (vermaj<asarver_maj) return;
1476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (dots==1)
1477 {
1478 if (strlen(vers[1])!=2) asar_throw_error(0, error_type_block, error_id_invalid_version_number);
1479 //if (asarver_min<10 && asarver_bug<10 && strlen(vers[1])>2) error(0, "This version of Asar is too old for this patch.");
1480 int verminbug=atoi(vers[1]);
1481 int tmpver=asarver_bug;
1482 if (tmpver>9) tmpver=9;
1483 if (asarver_min*10+tmpver<verminbug) asar_throw_error(pass, error_type_fatal, error_id_asar_too_old);
1484 }
1485 else
1486 {
1487 18 int vermin=atoi(vers[1]);
1488
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if (vermin>asarver_min) asar_throw_error(pass, error_type_fatal, error_id_asar_too_old);
1489 18 int verbug=atoi(vers[2]);
1490
2/6
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
18 if (vermin==asarver_min && verbug>asarver_bug) asar_throw_error(pass, error_type_fatal, error_id_asar_too_old);
1491 }
1492 108 }
1493
8/8
✓ Branch 0 taken 1863 times.
✓ Branch 1 taken 30348 times.
✓ Branch 2 taken 1857 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 28152 times.
✓ Branch 5 taken 4053 times.
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 28134 times.
32211 else if (is0("include") || is1("includefrom"))
1494 {
1495
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
24 if (!asarverallowed) asar_throw_error(0, error_type_block, error_id_start_of_file);
1496
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 if (in_top_level_file())
1497 {
1498
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 if (par) asar_throw_error(pass, error_type_fatal, error_id_cant_be_main_file, (string(" The main file is '") + par + "'.").data());
1499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 else asar_throw_error(pass, error_type_fatal, error_id_cant_be_main_file, "");
1500 }
1501 }
1502
4/4
✓ Branch 0 taken 1857 times.
✓ Branch 1 taken 30330 times.
✓ Branch 2 taken 1767 times.
✓ Branch 3 taken 90 times.
32187 else if (is0("includeonce"))
1503 {
1504
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 const char* current_file = get_current_file_name();
1505
2/4
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
90 if (!file_included_once(current_file))
1506 {
1507 90 includeonce.append(current_file);
1508 }
1509 }
1510
6/6
✓ Branch 0 taken 1980 times.
✓ Branch 1 taken 30117 times.
✓ Branch 2 taken 1710 times.
✓ Branch 3 taken 270 times.
✓ Branch 4 taken 270 times.
✓ Branch 5 taken 720 times.
32097 else if (numwords==3 && !stricmp(word[1], "="))
1511 {
1512
3/4
✓ Branch 0 taken 1206 times.
✓ Branch 1 taken 234 times.
✓ Branch 2 taken 1206 times.
✗ Branch 3 not taken.
1440 if(word[0][0] == '\'' && word[0][1])
1513 {
1514 int codepoint;
1515 1206 const char* char_start = word[0]+1;
1516
1/2
✓ Branch 0 taken 1206 times.
✗ Branch 1 not taken.
1206 const char* after = char_start + utf8_val(&codepoint, char_start);
1517
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1206 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1206 if (codepoint == -1) asar_throw_error(0, error_type_block, error_id_invalid_utf8);
1518
2/4
✓ Branch 0 taken 1206 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1206 times.
✗ Branch 3 not taken.
1206 if(after[0] == '\'' && after[1] == '\0') {
1519
3/4
✓ Branch 0 taken 1188 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 1188 times.
✗ Branch 3 not taken.
1206 thetable.set_val(codepoint, getnum(word[2]));
1520
3/6
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1170 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1188 if (foundlabel && !foundlabel_static) asar_throw_error(0, error_type_block, error_id_no_labels_here);
1521 1188 return;
1522 } // todo: error checking here
1523 }
1524 // randomdude999: int cast b/c i'm too lazy to also mess with making setlabel()
1525 // unsigned, besides it wouldn't matter anyways.
1526
1/2
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
234 int num=(int)getnum(word[2]);
1527
5/6
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 198 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
234 if (foundlabel && !foundlabel_static) asar_throw_error(0, error_type_block, error_id_label_cross_assignment);
1528
1529 216 const char* newlabelname = word[0];
1530 bool ismacro = false;
1531
1532
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 198 times.
216 if (newlabelname[0] == '?')
1533 {
1534 ismacro = true;
1535 18 newlabelname++;
1536 }
1537
1538
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (ismacro && macrorecursion == 0)
1539 {
1540 asar_throw_error(0, error_type_block, error_id_macro_label_outside_of_macro);
1541 }
1542
1543
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
216 if (!confirmname(newlabelname)) asar_throw_error(0, error_type_block, error_id_invalid_label_name);
1544
1545 108 string completename;
1546
1547
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 198 times.
216 if (ismacro)
1548 {
1549 36 completename += STR":macro_" + dec(calledmacros) + "_";
1550 }
1551
1552 216 completename += newlabelname;
1553
1554
1/2
✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
216 setlabel(ns + completename, num, true);
1555 216 }
1556
3/4
✓ Branch 0 taken 30657 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29952 times.
✓ Branch 3 taken 705 times.
30657 else if (assemblemapper(word, numwords)) {}
1557
4/4
✓ Branch 0 taken 28077 times.
✓ Branch 1 taken 1875 times.
✓ Branch 2 taken 25695 times.
✓ Branch 3 taken 2382 times.
29952 else if (is1("org"))
1558 {
1559
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2382 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2382 if(in_spcblock) asar_throw_error(0, error_type_block, error_id_feature_unavaliable_in_spcblock);
1560 2382 freespaceend();
1561
1/2
✓ Branch 0 taken 2382 times.
✗ Branch 1 not taken.
2382 unsigned int num=getnum(par);
1562
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2382 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2382 if (forwardlabel) asar_throw_error(0, error_type_block, error_id_org_label_forward);
1563
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2382 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2382 if (num&~0xFFFFFF) asar_throw_error(1, error_type_block, error_id_snes_address_out_of_bounds, hex(num, 6).data());
1564
5/10
✓ Branch 0 taken 813 times.
✓ Branch 1 taken 1569 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 795 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1587 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
2382 if ((mapper==lorom || mapper==exlorom) && (num&0x408000)==0x400000 && (num&0x700000)!=0x700000) asar_throw_warning(0, warning_id_set_middle_byte);
1565 //if (fastrom) num|=0x800000;
1566 2382 snespos=(int)num;
1567 2382 realsnespos=(int)num;
1568 2382 startpos=(int)num;
1569 2382 realstartpos=(int)num;
1570 2382 snespos_valid = true;
1571 }
1572 #define ret_error(errid) { asar_throw_error(0, error_type_block, errid); return; }
1573 #define ret_error_params(errid, ...) { asar_throw_error(0, error_type_block, errid, __VA_ARGS__); return; }
1574
2/2
✓ Branch 0 taken 270 times.
✓ Branch 1 taken 27300 times.
27570 else if (is("struct"))
1575 {
1576 //verifysnespos();
1577
2/6
✓ Branch 0 taken 270 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 270 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
270 if (in_struct || in_sub_struct) ret_error(error_id_nested_struct);
1578
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
270 if (numwords < 2) ret_error(error_id_missing_struct_params);
1579
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
270 if (numwords > 4) ret_error(error_id_too_many_struct_params);
1580
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 90 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
270 if (!confirmname(word[1])) ret_error(error_id_invalid_struct_name);
1581
1582
3/6
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 138 times.
✓ Branch 2 taken 132 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
270 if (structs.exists(word[1]) && pass == 0) ret_error_params(error_id_struct_redefined, word[1]);
1583
1584 270 static_struct = false;
1585 270 old_snespos = snespos;
1586 270 old_startpos = startpos;
1587 270 old_optimizeforbank = optimizeforbank;
1588 270 old_snespos_valid = snespos_valid;
1589 unsigned int base = 0;
1590
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 180 times.
270 if (numwords == 3)
1591 {
1592 90 static_struct = true;
1593
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 base = getnum(word[2]);
1594
1595
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
90 if (foundlabel && !foundlabel_static) static_struct = false;
1596 }
1597
1598 270 bool old_in_struct = in_struct;
1599 270 bool old_in_sub_struct = in_sub_struct;
1600 270 in_struct = numwords == 2 || numwords == 3;
1601 270 in_sub_struct = numwords == 4;
1602
1603 #define ret_error_cleanup(errid) { in_struct = old_in_struct; in_sub_struct = old_in_sub_struct; asar_throw_error(0, error_type_block, errid); return; }
1604 #define ret_error_params_cleanup(errid, ...) { in_struct = old_in_struct; in_sub_struct = old_in_sub_struct; asar_throw_error(0, error_type_block, errid, __VA_ARGS__); return; }
1605
1606
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 180 times.
270 if (numwords == 3)
1607 {
1608
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
90 if (base&~0xFFFFFF) ret_error_params_cleanup(error_id_snes_address_out_of_bounds, hex((unsigned int)base, 6).data());
1609 90 snespos = (int)base;
1610 90 startpos = (int)base;
1611 }
1612
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 108 times.
180 else if (numwords == 4)
1613 {
1614
3/6
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
72 if (strcasecmp(word[2], "extends")) ret_error_cleanup(error_id_missing_extends);
1615
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
72 if (!confirmname(word[3])) ret_error_cleanup(error_id_struct_invalid_parent_name);
1616 36 string tmp_struct_parent = word[3];
1617
1618
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
72 if (!structs.exists(tmp_struct_parent)) ret_error_params_cleanup(error_id_struct_not_found, tmp_struct_parent.data());
1619 72 snes_struct structure = structs.find(tmp_struct_parent);
1620
1621 72 static_struct = structure.is_static;
1622 struct_parent = tmp_struct_parent;
1623 72 snespos = structure.base_end;
1624 72 startpos = structure.base_end;
1625 72 }
1626
1627 270 push_pc();
1628
1629 270 optimizeforbank = -1;
1630
1631 270 struct_name = word[1];
1632 270 struct_base = snespos;
1633 270 realsnespos = 0;
1634 270 realstartpos = 0;
1635 270 snespos_valid = true;
1636
1637
1/2
✓ Branch 0 taken 270 times.
✗ Branch 1 not taken.
540 setlabel(ns + struct_name, snespos, static_struct);
1638
1639 #undef ret_error_cleanup
1640 #undef ret_error_params_cleanup
1641 }
1642
2/2
✓ Branch 0 taken 270 times.
✓ Branch 1 taken 27030 times.
27300 else if (is("endstruct"))
1643 {
1644
3/6
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 252 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
270 if (numwords != 1 && numwords != 3) ret_error(error_id_invalid_endstruct_count);
1645
5/8
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 252 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
270 if (numwords == 3 && strcasecmp(word[1], "align")) ret_error(error_id_expected_align);
1646
3/6
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 198 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 72 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
270 if (!in_struct && !in_sub_struct) ret_error(error_id_endstruct_without_struct);
1647
1648
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 252 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
270 int alignment = numwords == 3 ? (int)getnum(word[2]) : 1;
1649
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if (alignment < 1) ret_error(error_id_alignment_too_small);
1650
1651 snes_struct structure;
1652 270 structure.base_end = snespos;
1653 270 structure.struct_size = alignment * ((snespos - struct_base + alignment - 1) / alignment);
1654 270 structure.object_size = structure.struct_size;
1655 270 structure.is_static = static_struct;
1656
1657
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 72 times.
270 if (in_struct)
1658 {
1659
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 structs.create(struct_name) = structure;
1660 }
1661
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 else if (in_sub_struct)
1662 {
1663 snes_struct parent;
1664 72 parent = structs.find(struct_parent);
1665
1666
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (parent.object_size < parent.struct_size + structure.struct_size) {
1667 72 parent.object_size = parent.struct_size + structure.struct_size;
1668 }
1669
1670
2/4
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
72 structs.create(struct_parent + "." + struct_name) = structure;
1671
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 structs.create(struct_parent) = parent;
1672 }
1673
1674 270 pop_pc();
1675 270 in_struct = false;
1676 270 in_sub_struct = false;
1677 270 snespos = old_snespos;
1678 270 startpos = old_startpos;
1679 270 optimizeforbank = old_optimizeforbank;
1680 270 snespos_valid = old_snespos_valid;
1681 270 static_struct = false;
1682 }
1683 #undef ret_error
1684
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 27012 times.
27030 else if(is("spcblock"))
1685 {
1686 //banned features when active: org, freespace(and variants), arch, mapper,namespace,pushns
1687
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if(arch != arch_spc700) asar_throw_error(0, error_type_block, error_id_spcblock_bad_arch);
1688
2/6
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
18 if(in_struct || in_sub_struct) asar_throw_error(0, error_type_block, error_id_spcblock_inside_struct);
1689
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if(numwords < 2) asar_throw_error(0, error_type_block, error_id_spcblock_too_few_args);
1690
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if(numwords > 4) asar_throw_error(0, error_type_block, error_id_spcblock_too_many_args);
1691
1692
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 spcblock.destination = getnum(par);
1693 18 spcblock.type = spcblock_nspc;
1694 spcblock.macro_name = "";
1695
1696
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if (spcblock.destination&~0xFFFF) asar_throw_error(0, error_type_block, error_id_snes_address_out_of_bounds, hex(spcblock.destination, 6).data());
1697
1698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if(numwords == 3)
1699 {
1700 if(!stricmp(word[2], "nspc")) spcblock.type = spcblock_nspc;
1701 else if(!stricmp(word[2], "custom")) asar_throw_error(0, error_type_block, error_id_custom_spcblock_missing_macro);
1702 else asar_throw_error(0, error_type_block, error_id_unknown_spcblock_type);
1703 }
1704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 else if(numwords == 4)
1705 {
1706 if(!stricmp(word[2], "custom")) spcblock.type = spcblock_custom;
1707 else asar_throw_error(0, error_type_block, error_id_extra_spcblock_arg_for_type);
1708
1709 if(macros.exists(word[3]))
1710 {
1711 macrodata *macro = macros.find(word[3]);
1712 if(!macro->variadic) asar_throw_error(0, error_type_block, error_id_spcblock_macro_must_be_varadic);
1713 if(macro->numargs != 3) asar_throw_error(0, error_type_block, error_id_spcblock_macro_invalid_static_args);
1714 spcblock.macro_name = word[3];
1715 }
1716 else asar_throw_error(0, error_type_block, error_id_spcblock_macro_doesnt_exist);
1717 }
1718
1719
1/3
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
18 switch(spcblock.type)
1720 {
1721 18 case spcblock_nspc:
1722 18 spcblock.size_address=realsnespos;
1723
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 write2(0x0000);
1724
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 write2(spcblock.destination);
1725 18 snespos=(int)spcblock.destination;
1726 18 startpos=(int)spcblock.destination;
1727 18 spcblock.execute_address = -1u;
1728
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 add_addr_to_line(addrToLinePos);
1729 break;
1730 case spcblock_custom:
1731 //this is a todo that probably won't be ready for 1.9
1732 //mostly so we can leverage some cleanups we make in 2.0 for practicality
1733 asar_throw_error(0, error_type_block, error_id_spcblock_custom_types_incomplete);
1734 push_pc();
1735 spcblock.old_mapper = mapper;
1736 mapper = norom;
1737 break;
1738 default:
1739 asar_throw_error(0, error_type_fatal, error_id_internal_error, "invalid spcblock type");
1740 }
1741
1742 ns_backup = ns;
1743 27 ns = STR":SPCBLOCK:_" + ns_backup;
1744 18 in_spcblock = true;
1745 }
1746
4/4
✓ Branch 0 taken 867 times.
✓ Branch 1 taken 26145 times.
✓ Branch 2 taken 849 times.
✓ Branch 3 taken 18 times.
27012 else if(is0("endspcblock"))
1747 {
1748
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if(!in_spcblock) asar_throw_error(0, error_type_block, error_id_endspcblock_without_spcblock);
1749
1750
1/3
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
18 switch(spcblock.type)
1751 {
1752 18 case spcblock_nspc:
1753
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if (pass==2)
1754 {
1755
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
6 int pcpos=snestopc(spcblock.size_address&0xFFFFFF);
1756
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 if (pcpos<0) asar_throw_error(2, error_type_block, error_id_snes_address_doesnt_map_to_rom, hex((unsigned int)realsnespos, 6).data());
1757 6 int num=snespos-startpos;
1758
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 writeromdata_byte(pcpos, (unsigned char)num);
1759
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 writeromdata_byte(pcpos+1, (unsigned char)(num >> 8));
1760 }
1761
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if(spcblock.execute_address != -1u)
1762 {
1763
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 write2(0x0000);
1764
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 write2((unsigned int)spcblock.execute_address);
1765 }
1766 break;
1767 case spcblock_custom:
1768 mapper = spcblock.old_mapper;
1769 pop_pc();
1770 break;
1771 default:
1772 asar_throw_error(0, error_type_fatal, error_id_internal_error, "invalid spcblock type");
1773 }
1774 ns = ns_backup;
1775 18 in_spcblock = false;
1776 }
1777
4/4
✓ Branch 0 taken 25569 times.
✓ Branch 1 taken 1425 times.
✓ Branch 2 taken 25551 times.
✓ Branch 3 taken 18 times.
26994 else if (is1("startpos"))
1778 {
1779
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if(!in_spcblock) asar_throw_error(0, error_type_block, error_id_startpos_without_spcblock);
1780
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 spcblock.execute_address=getnum(par);
1781 }
1782
4/4
✓ Branch 0 taken 25551 times.
✓ Branch 1 taken 1425 times.
✓ Branch 2 taken 25281 times.
✓ Branch 3 taken 270 times.
26976 else if (is1("base"))
1783 {
1784
4/4
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 90 times.
270 if (!stricmp(par, "off"))
1785 {
1786 90 snespos=realsnespos;
1787 90 startpos=realstartpos;
1788 90 snespos_valid = realsnespos >= 0;
1789 90 return;
1790 }
1791
1/2
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
180 unsigned int num=getnum(par);
1792
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 180 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
180 if (forwardlabel) asar_throw_error(0, error_type_block, error_id_base_label_invalid);
1793
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 180 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
180 if (num&~0xFFFFFF) asar_throw_error(1, error_type_block, error_id_snes_address_out_of_bounds, hex((unsigned int)num).data());
1794 180 snespos=(int)num;
1795 180 startpos=(int)num;
1796 180 optimizeforbank=-1;
1797 180 snespos_valid = realsnespos >= 0;
1798 }
1799
4/4
✓ Branch 0 taken 25281 times.
✓ Branch 1 taken 1425 times.
✓ Branch 2 taken 25245 times.
✓ Branch 3 taken 36 times.
26706 else if (is1("dpbase"))
1800 {
1801
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 unsigned int num=(int)getnum(par);
1802
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
36 if (forwardlabel) asar_throw_error(0, error_type_block, error_id_base_label_invalid);
1803
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
36 if (num&~0xFF00) asar_throw_error(1, error_type_block, error_id_bad_dp_base, hex((unsigned int)num, 6).data());
1804 36 dp_base = (int)num;
1805 }
1806
4/4
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 26238 times.
✓ Branch 2 taken 324 times.
✓ Branch 3 taken 108 times.
26670 else if (is2("optimize"))
1807 {
1808
4/4
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 18 times.
108 if (!stricmp(par, "dp"))
1809 {
1810
4/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 27 times.
72 if (!stricmp(word[2], "none"))
1811 {
1812 18 optimize_dp = optimize_dp_flag::NONE;
1813 18 return;
1814 }
1815
4/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 18 times.
54 if (!stricmp(word[2], "ram"))
1816 {
1817 18 optimize_dp = optimize_dp_flag::RAM;
1818 18 return;
1819 }
1820
2/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
36 if (!stricmp(word[2], "always"))
1821 {
1822 36 optimize_dp = optimize_dp_flag::ALWAYS;
1823 36 return;
1824 }
1825 asar_throw_error(1, error_type_block, error_id_bad_dp_optimize, word[2]);
1826 }
1827
2/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
36 if (!stricmp(par, "address"))
1828 {
1829
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
36 if (!stricmp(word[2], "default"))
1830 {
1831 optimize_address = optimize_address_flag::DEFAULT;
1832 return;
1833 }
1834
4/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9 times.
36 if (!stricmp(word[2], "ram"))
1835 {
1836 18 optimize_address = optimize_address_flag::RAM;
1837 18 return;
1838 }
1839
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
18 if (!stricmp(word[2], "mirrors"))
1840 {
1841 18 optimize_address = optimize_address_flag::MIRRORS;
1842 18 return;
1843 }
1844 asar_throw_error(1, error_type_block, error_id_bad_address_optimize, word[2]);
1845 }
1846 asar_throw_error(1, error_type_block, error_id_bad_optimize, par);
1847 }
1848
4/4
✓ Branch 0 taken 25245 times.
✓ Branch 1 taken 1317 times.
✓ Branch 2 taken 25191 times.
✓ Branch 3 taken 54 times.
26562 else if (is1("bank"))
1849 {
1850
4/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 18 times.
54 if (!stricmp(par, "auto"))
1851 {
1852 18 optimizeforbank=-1;
1853 18 return;
1854 }
1855
4/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9 times.
36 if (!stricmp(par, "noassume"))
1856 {
1857 18 optimizeforbank=0x100;
1858 18 return;
1859 }
1860
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 unsigned int num=getnum(par);
1861 //if (forwardlabel) error(0, "bank Label is not valid");
1862 //if (foundlabel) num>>=16;
1863
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if (num&~0x0000FF) asar_throw_error(1, error_type_block, error_id_snes_address_out_of_bounds, hex((unsigned int)num, 6).data());
1864 18 optimizeforbank=(int)num;
1865 }
1866
8/8
✓ Branch 0 taken 26490 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 23268 times.
✓ Branch 3 taken 3222 times.
✓ Branch 4 taken 22386 times.
✓ Branch 5 taken 882 times.
✓ Branch 6 taken 22116 times.
✓ Branch 7 taken 270 times.
26508 else if (is("freespace") || is("freecode") || is("freedata") || is("segment"))
1867 {
1868
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4392 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4392 if(in_spcblock) asar_throw_error(0, error_type_block, error_id_feature_unavaliable_in_spcblock);
1869 2196 string parstr;
1870
2/2
✓ Branch 0 taken 396 times.
✓ Branch 1 taken 3996 times.
4392 if (numwords==1) parstr="\n";//crappy hack: impossible character to cut out extra commas
1871
1/2
✓ Branch 0 taken 3996 times.
✗ Branch 1 not taken.
3996 else if (numwords==2) parstr=word[1];
1872 else asar_throw_error(0, error_type_block, error_id_invalid_freespace_request);
1873
2/2
✓ Branch 0 taken 3222 times.
✓ Branch 1 taken 1170 times.
7614 if (is("freecode")) parstr=STR"ram,"+parstr;
1874
2/2
✓ Branch 0 taken 882 times.
✓ Branch 1 taken 3510 times.
5274 if (is("freedata")) parstr=STR"noram,"+parstr;
1875
2/2
✓ Branch 0 taken 270 times.
✓ Branch 1 taken 4122 times.
4662 if (is("segment")) parstr = STR "norats," + parstr;
1876
1/2
✓ Branch 0 taken 4392 times.
✗ Branch 1 not taken.
4392 autoptr<char**> pars=split(parstr.temp_raw(), ',');
1877 unsigned char fsbyte = 0x00;
1878 bool fixedpos=false;
1879 bool align=false;
1880 bool leakwarn=true;
1881 bool write_rats=true;
1882 int target_bank = -3;
1883 2196 string pin_to_freespace = "";
1884 int search_start_pos = -1;
1885
1886
2/2
✓ Branch 0 taken 8802 times.
✓ Branch 1 taken 4392 times.
13194 for (int i=0;pars[i];i++)
1887 {
1888
2/2
✓ Branch 0 taken 8406 times.
✓ Branch 1 taken 396 times.
8802 if (pars[i][0]=='\n') {}
1889
4/4
✓ Branch 0 taken 5814 times.
✓ Branch 1 taken 2592 times.
✓ Branch 2 taken 1611 times.
✓ Branch 3 taken 2592 times.
8406 else if (!stricmp(pars[i], "ram"))
1890 {
1891
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3222 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3222 if (target_bank!=-3) asar_throw_error(0, error_type_block, error_id_invalid_freespace_request);
1892 target_bank = -2;
1893 }
1894
4/4
✓ Branch 0 taken 3033 times.
✓ Branch 1 taken 2151 times.
✓ Branch 2 taken 441 times.
✓ Branch 3 taken 2151 times.
5184 else if (!stricmp(pars[i], "noram"))
1895 {
1896
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
882 if (target_bank!=-3) asar_throw_error(0, error_type_block, error_id_invalid_freespace_request);
1897 target_bank = -1;
1898 }
1899
4/4
✓ Branch 0 taken 2169 times.
✓ Branch 1 taken 2133 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 2133 times.
4302 else if (!stricmp(pars[i], "static"))
1900 {
1901
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
36 if (fixedpos) asar_throw_error(0, error_type_block, error_id_invalid_freespace_request);
1902 fixedpos=true;
1903 }
1904
4/4
✓ Branch 0 taken 2151 times.
✓ Branch 1 taken 2115 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 2115 times.
4266 else if (!stricmp(pars[i], "align"))
1905 {
1906
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
36 if (align) asar_throw_error(0, error_type_block, error_id_invalid_freespace_request);
1907 align=true;
1908 }
1909
4/4
✓ Branch 0 taken 3996 times.
✓ Branch 1 taken 234 times.
✓ Branch 2 taken 1881 times.
✓ Branch 3 taken 234 times.
4230 else if (!stricmp(pars[i], "cleaned"))
1910 {
1911
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3762 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3762 if (!leakwarn) asar_throw_error(0, error_type_block, error_id_invalid_freespace_request);
1912 leakwarn=false;
1913 }
1914
4/4
✓ Branch 0 taken 333 times.
✓ Branch 1 taken 135 times.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 135 times.
468 else if (!stricmp(pars[i], "norats"))
1915 {
1916 write_rats=false;
1917 }
1918
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 108 times.
198 else if (stribegin(pars[i], "bank="))
1919 {
1920
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
90 if(target_bank != -3) asar_throw_error(0, error_type_block, error_id_invalid_freespace_request);
1921
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 target_bank = getnum(pars[i] + 5);
1922
1/6
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
90 if(foundlabel && !foundlabel_static) asar_throw_error(0, error_type_block, error_id_no_labels_here);
1923 }
1924
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 72 times.
108 else if (stribegin(pars[i], "start="))
1925 {
1926
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 search_start_pos = getnum(pars[i] + 6);
1927
1/6
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
36 if(foundlabel && !foundlabel_static) asar_throw_error(0, error_type_block, error_id_no_labels_here);
1928 }
1929
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 else if (stribegin(pars[i], "pin="))
1930 {
1931 // TODO: should we handle posneg labels here too?
1932 72 string pin_to = pars[i] + 4;
1933 72 const char* pin_to_c = pin_to.data();
1934
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 pin_to_freespace = labelname(&pin_to_c);
1935
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
72 if(*pin_to_c) asar_throw_error(0, error_type_block, error_id_invalid_label_name);
1936 // this is to throw an "undefined label" error with the proper callstack
1937
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
96 if(pass) labelval(pin_to);
1938 72 }
1939 else if (stribegin(pars[i], "cleanbyte="))
1940 {
1941 fsbyte = getnum(pars[i] + strlen("cleanbyte="));
1942 if(foundlabel && !foundlabel_static) asar_throw_error(0, error_type_block, error_id_no_labels_here);
1943 }
1944 else
1945 {
1946 // for backwards compat i guess
1947 fsbyte = (unsigned char)getnum(pars[i]);
1948 }
1949 }
1950
2/2
✓ Branch 0 taken 4194 times.
✓ Branch 1 taken 198 times.
4392 if(target_bank == -3 && !write_rats) target_bank = -1;
1951
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4194 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4194 if(target_bank == -3) asar_throw_error(0, error_type_block, error_id_invalid_freespace_request);
1952 // no point specifying anything about cleaning when not writing a rats tag
1953
3/6
✓ Branch 0 taken 270 times.
✓ Branch 1 taken 4122 times.
✓ Branch 2 taken 270 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4392 if(!write_rats && (!leakwarn || fixedpos)) asar_throw_error(0, error_type_block, error_id_invalid_freespace_request);
1954 if(!write_rats) leakwarn = false;
1955 4392 freespaceend();
1956 4392 freespaceid=getfreespaceid();
1957 freespace_data& thisfs = freespaces[freespaceid];
1958 4392 thisfs.cleanbyte = fsbyte;
1959
1960 4392 thisfs.pin_target = pin_to_freespace;
1961
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 4320 times.
4392 if(pin_to_freespace) thisfs.pin_target_ns = ns;
1962 4392 thisfs.write_rats = write_rats;
1963 4392 thisfs.search_start = search_start_pos;
1964 4392 thisfs.bank = target_bank;
1965 4392 thisfs.flag_align = align;
1966
1967
2/2
✓ Branch 0 taken 1464 times.
✓ Branch 1 taken 2928 times.
4392 if (pass==0) snespos=0;
1968
2/2
✓ Branch 0 taken 1464 times.
✓ Branch 1 taken 2928 times.
4392 if (pass==1)
1969 {
1970
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1452 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
1464 if (fixedpos && thisfs.orgpos<0)
1971 {
1972 thisfs.pos = 0;
1973 thisfs.leaked = false;//mute some other errors
1974 asar_throw_error(1, error_type_block, error_id_static_freespace_autoclean);
1975 }
1976 1464 snespos = 0;
1977 }
1978
2/2
✓ Branch 0 taken 1464 times.
✓ Branch 1 taken 2928 times.
4392 if (pass==2)
1979 {
1980
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1452 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
1464 if (fixedpos && thisfs.orgpos == -1) return;//to kill some errors
1981 1464 snespos=thisfs.pos;
1982
3/6
✓ Branch 0 taken 1338 times.
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1338 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1464 if (thisfs.leaked && leakwarn) asar_throw_warning(2, warning_id_freespace_leaked);
1983
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 1374 times.
1464 freespaceuse += (write_rats ? 8 : 0) + thisfs.len;
1984
1985 // add a mapping for the start of the rats tag
1986
3/4
✓ Branch 0 taken 1374 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 1374 times.
✗ Branch 3 not taken.
1464 if (write_rats) add_addr_to_line(snespos-8);
1987 }
1988 4392 thisfs.is_static = fixedpos;
1989
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4392 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4392 if (snespos < 0 && mapper == sa1rom) asar_throw_error(pass, error_type_fatal, error_id_no_freespace_in_mapped_banks, dec(thisfs.len).data());
1990
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4392 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4392 if (snespos < 0) asar_throw_error(pass, error_type_fatal, error_id_no_freespace, dec(thisfs.len).data());
1991
2/2
✓ Branch 0 taken 270 times.
✓ Branch 1 taken 4122 times.
4392 bytes+=write_rats ? 8 : 0;
1992 4392 freespacestart=snespos;
1993 4392 startpos=snespos;
1994 4392 realstartpos=snespos;
1995 4392 realsnespos=snespos;
1996 4392 optimizeforbank=-1;
1997
2/2
✓ Branch 0 taken 270 times.
✓ Branch 1 taken 4122 times.
4392 ratsmetastate=write_rats ? ratsmeta_allow : ratsmeta_ban;
1998 4392 snespos_valid = true;
1999 // check this at the very end so that snespos gets set properly, to
2000 // prevent spurious errors later
2001 //...i guess this can still cause bankcross errors if the old freespace
2002 //happened to be very close to the end of a bank or something, but
2003 //whatever
2004
7/8
✓ Branch 0 taken 1464 times.
✓ Branch 1 taken 2928 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 1452 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
4392 if (pass == 2 && fixedpos && thisfs.orgpos > 0 && thisfs.len > thisfs.orglen)
2005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 asar_throw_error(2, error_type_block, error_id_static_freespace_growing);
2006 4404 }
2007
4/4
✓ Branch 0 taken 21195 times.
✓ Branch 1 taken 921 times.
✓ Branch 2 taken 21051 times.
✓ Branch 3 taken 144 times.
22116 else if (is1("prot"))
2008 {
2009
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
144 if(in_spcblock) asar_throw_error(0, error_type_block, error_id_feature_unavaliable_in_spcblock);
2010
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
144 if (!ratsmetastate) asar_throw_error(2, error_type_block, error_id_prot_not_at_freespace_start);
2011
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 108 times.
144 if (ratsmetastate==ratsmeta_used) step(-5);
2012 int num;
2013
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 autoptr<char**> pars=qpsplit(par, ',', &num);
2014
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 verify_paren(pars);
2015
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 write1('P');
2016
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 write1('R');
2017
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 write1('O');
2018
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 write1('T');
2019
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
144 if (num * 3 > 255) asar_throw_error(0, error_type_block, error_id_prot_too_many_entries);
2020
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 write1((unsigned int)(num*3));
2021
2/2
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 144 times.
324 for (int i=0;i<num;i++)
2022 {
2023 //int num=getnum(pars[i]);
2024 180 const char * labeltest=pars[i];
2025 90 string testlabel = labeltest;
2026
1/2
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
180 snes_label lblval = labelval(&labeltest);
2027
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 180 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
180 if (*labeltest) asar_throw_error(0, error_type_block, error_id_label_not_found, testlabel.data());
2028
1/2
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
180 write3(lblval.pos);
2029
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 120 times.
180 if (pass==1) freespaces[lblval.freespace_id].leaked = false;
2030 180 }
2031
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 write1('S');
2032
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 write1('T');
2033
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 write1('O');
2034
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 write1('P');
2035
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 write1(0);
2036 144 ratsmetastate=ratsmeta_used;
2037
2038
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 add_addr_to_line(addrToLinePos);
2039 144 }
2040
7/8
✓ Branch 0 taken 21051 times.
✓ Branch 1 taken 921 times.
✓ Branch 2 taken 21051 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 324 times.
✓ Branch 5 taken 21648 times.
✓ Branch 6 taken 216 times.
✓ Branch 7 taken 108 times.
21972 else if (is1("autoclean") || is2("autoclean"))
2041 {
2042
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
216 if(in_spcblock) asar_throw_error(0, error_type_block, error_id_feature_unavaliable_in_spcblock);
2043
1/2
✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
216 if (numwords==3)
2044 {
2045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
216 if(freespaceid > 0)
2046 asar_throw_error(0, error_type_block, error_id_autoclean_in_freespace);
2047 216 const char * labeltest = word[2];
2048 108 string testlabel = labeltest;
2049
1/2
✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
216 snes_label lblval = labelval(&labeltest);
2050
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
216 if (*labeltest) asar_throw_error(0, error_type_block, error_id_label_not_found, testlabel.data());
2051 216 int targetid= lblval.freespace_id;
2052
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 144 times.
288 if (pass==1) freespaces[targetid].leaked = false;
2053 216 int num = lblval.pos;
2054
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
216 if (strlen(par)>3 && !stricmp(par+3, ".l")) par[3]=0;
2055
7/8
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 117 times.
✓ Branch 3 taken 54 times.
✓ Branch 4 taken 63 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✓ Branch 7 taken 54 times.
216 if (!stricmp(par, "JSL") || !stricmp(par, "JML"))
2056 {
2057
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
198 int orgpos=read3(snespos+1);
2058 198 int ratsloc=freespaces[targetid].orgpos;
2059
4/4
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 45 times.
198 int firstbyte = ((!stricmp(par, "JSL")) ? 0x22 : 0x5C);
2060
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
198 int pcpos=snestopc(snespos);
2061
4/6
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 198 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 72 times.
✓ Branch 5 taken 126 times.
198 if (/*pass==1 && */pcpos>=0 && pcpos<romlen_r && romdata_r[pcpos]==firstbyte)
2062 {
2063
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 ratsloc=ratsstart(orgpos)+8;
2064
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
72 freespaces[targetid].orglen=read2(ratsloc-4)+1;
2065
5/6
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
90 if (!freespaces[targetid].is_static && pass==1) removerats(orgpos, freespaces[targetid].cleanbyte);
2066 }
2067 126 else if (ratsloc<0) ratsloc=0;
2068
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 write1((unsigned int)firstbyte);
2069
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 write3((unsigned int)num);
2070
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 132 times.
198 if (pass==2)
2071 {
2072
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 int start=ratsstart(num);
2073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (start>=num || start<0)
2074 {
2075 asar_throw_error(2, error_type_block, error_id_autoclean_label_at_freespace_end);
2076 }
2077
2078
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 add_addr_to_line(addrToLinePos);
2079 }
2080 //freespaceorglen[targetid]=read2(ratsloc-4)+1;
2081 198 freespaces[targetid].orgpos = ratsloc;
2082 99 }
2083
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
18 else if (!stricmp(par, "dl"))
2084 {
2085
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
18 int orgpos=read3(snespos);
2086 18 int ratsloc=freespaces[targetid].orgpos;
2087
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 int start=ratsstart(num);
2088
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
18 if (pass==1 && num>=0)
2089 {
2090
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 ratsloc=ratsstart(orgpos)+8;
2091
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
12 if (!freespaces[targetid].is_static) removerats(orgpos, freespaces[targetid].cleanbyte);
2092 }
2093 else if (!ratsloc) ratsloc=0;
2094
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
18 if ((start==num || start<0) && pass==2)
2095 asar_throw_error(2, error_type_block, error_id_autoclean_label_at_freespace_end);
2096
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 write3((unsigned int)num);
2097 18 freespaces[targetid].orgpos = ratsloc;
2098
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
18 freespaces[targetid].orglen = read2(ratsloc-4)+1;
2099
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 add_addr_to_line(addrToLinePos);
2100 }
2101 else asar_throw_error(0, error_type_block, error_id_broken_autoclean);
2102 216 }
2103 // weird gotcha: we don't know the freespace id here, so we don't know what clean_byte to use
2104 else if (pass==0) removerats((int)getnum(word[1]), 0x00);
2105 }
2106
4/4
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 21303 times.
✓ Branch 2 taken 435 times.
✓ Branch 3 taken 18 times.
21756 else if (is0("pushpc"))
2107 {
2108
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 verifysnespos();
2109 18 pushpc[pushpcnum].arch=arch;
2110 18 pushpc[pushpcnum].snespos=snespos;
2111 18 pushpc[pushpcnum].snesstart=startpos;
2112 18 pushpc[pushpcnum].snesposreal=realsnespos;
2113 18 pushpc[pushpcnum].snesstartreal=realstartpos;
2114 18 pushpc[pushpcnum].freeid=freespaceid;
2115 18 pushpc[pushpcnum].freest=freespacestart;
2116 18 pushpcnum++;
2117 18 snespos=(int)0xFFFFFFFF;
2118 18 startpos= (int)0xFFFFFFFF;
2119 18 realsnespos= (int)0xFFFFFFFF;
2120 18 realstartpos= (int)0xFFFFFFFF;
2121 18 snespos_valid = false;
2122 }
2123
4/4
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 21303 times.
✓ Branch 2 taken 417 times.
✓ Branch 3 taken 18 times.
21738 else if (is0("pullpc"))
2124 {
2125
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if (!pushpcnum) asar_throw_error(0, error_type_block, error_id_pullpc_without_pushpc);
2126 18 pushpcnum--;
2127 18 freespaceend();
2128
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if (arch != pushpc[pushpcnum].arch) asar_throw_error(0, error_type_block, error_id_pullpc_different_arch);
2129 18 snespos=pushpc[pushpcnum].snespos;
2130 18 startpos=pushpc[pushpcnum].snesstart;
2131 18 realsnespos=pushpc[pushpcnum].snesposreal;
2132 18 realstartpos=pushpc[pushpcnum].snesstartreal;
2133 18 freespaceid=pushpc[pushpcnum].freeid;
2134 18 freespacestart=pushpc[pushpcnum].freest;
2135 18 snespos_valid = true;
2136 }
2137
4/4
✓ Branch 0 taken 417 times.
✓ Branch 1 taken 21303 times.
✓ Branch 2 taken 399 times.
✓ Branch 3 taken 18 times.
21720 else if (is0("pushbase"))
2138 {
2139 18 basestack[basestacknum] = snespos;
2140 18 basestacknum++;
2141 }
2142
4/4
✓ Branch 0 taken 399 times.
✓ Branch 1 taken 21303 times.
✓ Branch 2 taken 381 times.
✓ Branch 3 taken 18 times.
21702 else if (is0("pullbase"))
2143 {
2144
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if (!basestacknum) asar_throw_error(0, error_type_block, error_id_pullbase_without_pushbase);
2145 18 basestacknum--;
2146 18 snespos = basestack[basestacknum];
2147 18 startpos = basestack[basestacknum];
2148
2149
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (snespos != realstartpos)
2150 {
2151 18 optimizeforbank = -1;
2152 }
2153 }
2154
4/4
✓ Branch 0 taken 381 times.
✓ Branch 1 taken 21303 times.
✓ Branch 2 taken 345 times.
✓ Branch 3 taken 36 times.
21684 else if (is0("pushns"))
2155 {
2156
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
36 if(in_spcblock) asar_throw_error(0, error_type_block, error_id_feature_unavaliable_in_spcblock);
2157 36 pushns[pushnsnum].ns = ns;
2158
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
72 for(int i = 0; i < namespace_list.count; i++)
2159 {
2160 36 pushns[pushnsnum].namespace_list.append(namespace_list[i]);
2161 }
2162 36 pushns[pushnsnum].nested_namespaces = nested_namespaces;
2163 36 pushnsnum++;
2164
2165 36 namespace_list.reset();
2166 ns = "";
2167 36 nested_namespaces = false;
2168 }
2169
4/4
✓ Branch 0 taken 345 times.
✓ Branch 1 taken 21303 times.
✓ Branch 2 taken 309 times.
✓ Branch 3 taken 36 times.
21648 else if (is0("pullns"))
2170 {
2171
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
36 if(in_spcblock) asar_throw_error(0, error_type_block, error_id_feature_unavaliable_in_spcblock);
2172
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
36 if (!pushnsnum) asar_throw_error(0, error_type_block, error_id_pullns_without_pushns);
2173 36 pushnsnum--;
2174 36 ns = pushns[pushnsnum].ns;
2175 36 nested_namespaces = pushns[pushnsnum].nested_namespaces;
2176 36 namespace_list.reset();
2177
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 36 times.
108 for(int i = 0; i < pushns[pushnsnum].namespace_list.count; i++)
2178 {
2179 72 namespace_list.append(pushns[pushnsnum].namespace_list[i]);
2180 }
2181 }
2182
7/8
✓ Branch 0 taken 21051 times.
✓ Branch 1 taken 561 times.
✓ Branch 2 taken 20670 times.
✓ Branch 3 taken 381 times.
✓ Branch 4 taken 108 times.
✓ Branch 5 taken 21123 times.
✓ Branch 6 taken 108 times.
✗ Branch 7 not taken.
21612 else if (is1("namespace") || is2("namespace"))
2183 {
2184
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 489 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
489 if(in_spcblock) asar_throw_error(0, error_type_block, error_id_feature_unavaliable_in_spcblock);
2185 bool leave = false;
2186
1/2
✓ Branch 0 taken 489 times.
✗ Branch 1 not taken.
489 if (par)
2187 {
2188
4/4
✓ Branch 0 taken 315 times.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 171 times.
489 if (!stricmp(par, "off"))
2189 {
2190
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
144 if (word[2]) asar_throw_error(0, error_type_block, error_id_invalid_namespace_use);
2191 leave = true;
2192 }
2193
4/4
✓ Branch 0 taken 225 times.
✓ Branch 1 taken 120 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 117 times.
345 else if (!stricmp(par, "nested"))
2194 {
2195
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
108 if (!word[2]) asar_throw_error(0, error_type_block, error_id_invalid_namespace_use);
2196
4/4
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 27 times.
108 else if (!stricmp(word[2], "on")) nested_namespaces = true;
2197
2/4
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
54 else if (!stricmp(word[2], "off")) nested_namespaces = false;
2198 }
2199 else
2200 {
2201
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
237 if (word[2]) asar_throw_error(0, error_type_block, error_id_invalid_namespace_use);
2202
1/2
✓ Branch 0 taken 237 times.
✗ Branch 1 not taken.
237 const char * tmpstr= safedequote(par);
2203
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 81 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
237 if (!confirmname(tmpstr)) asar_throw_error(0, error_type_block, error_id_invalid_namespace_name);
2204
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 144 times.
237 if (!nested_namespaces)
2205 {
2206 93 namespace_list.reset();
2207 }
2208 237 namespace_list.append(tmpstr);
2209 }
2210 }
2211 else
2212 {
2213 leave = true;
2214 }
2215
2216 if (leave)
2217 {
2218
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 36 times.
144 if (nested_namespaces)
2219 {
2220 108 namespace_list.remove(namespace_list.count - 1);
2221 }
2222 else
2223 {
2224 36 namespace_list.reset();
2225 }
2226 }
2227
2228 // recompute ns
2229 ns = "";
2230
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 489 times.
1068 for (int i = 0; i < namespace_list.count; i++)
2231 {
2232 579 ns += namespace_list[i];
2233 579 ns += "_";
2234 }
2235 }
2236
4/4
✓ Branch 0 taken 20670 times.
✓ Branch 1 taken 453 times.
✓ Branch 2 taken 20598 times.
✓ Branch 3 taken 72 times.
21123 else if (is1("warnpc"))
2237 {
2238
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 unsigned int maxpos=getnum(par);
2239
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
72 if (freespaceid > 0) asar_throw_error(0, error_type_block, error_id_warnpc_in_freespace);
2240
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
54 if ((unsigned int)maxpos & 0xFF000000) asar_throw_error(0, error_type_block, error_id_warnpc_broken_param);
2241
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
54 if ((unsigned int)snespos > maxpos) asar_throw_error(0, error_type_block, error_id_warnpc_failed, hex((unsigned int)snespos).data(), hex((unsigned int)maxpos, 6).data());
2242 }
2243 #ifdef SANDBOX
2244 else if (is("incsrc") || is("incbin") || is("table"))
2245 {
2246 asar_throw_error(0, error_type_block, error_id_command_disabled);
2247 }
2248 #endif
2249
4/4
✓ Branch 0 taken 20598 times.
✓ Branch 1 taken 453 times.
✓ Branch 2 taken 3606 times.
✓ Branch 3 taken 16992 times.
21051 else if (is1("incsrc"))
2250 {
2251 1755 string name;
2252 // RPG Hacker: Should this also throw on absolute paths?
2253 // E.g., on something starting with C:/ or whatever.
2254
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 16974 times.
16992 if (strchr(par, '\\'))
2255 {
2256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 asar_throw_error(0, error_type_block, error_id_platform_paths);
2257 }
2258
1/2
✓ Branch 0 taken 16974 times.
✗ Branch 1 not taken.
16974 name=safedequote(par);
2259
2/2
✓ Branch 0 taken 474 times.
✓ Branch 1 taken 16500 times.
16974 assemblefile(name);
2260 16992 }
2261
8/8
✓ Branch 0 taken 3606 times.
✓ Branch 1 taken 453 times.
✓ Branch 2 taken 3390 times.
✓ Branch 3 taken 216 times.
✓ Branch 4 taken 126 times.
✓ Branch 5 taken 3717 times.
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 108 times.
4059 else if (is1("incbin") || is3("incbin"))
2262 {
2263
3/6
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
234 if (numwords == 4 && strcmp(word[2], "->")) asar_throw_error(0, error_type_block, error_id_broken_incbin);
2264 int len;
2265 int start=0;
2266 int end=0;
2267
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 108 times.
234 if (strqchr(par, ':'))
2268 {
2269 char * lengths=strqchr(par, ':');
2270 126 *lengths=0;
2271 126 lengths++;
2272
2273
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 char* split = strqpstr(lengths, "..");
2274
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
126 if(!split) asar_throw_error(0, error_type_block, error_id_broken_incbin);
2275 108 string start_str(lengths, split-lengths);
2276
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
108 if(start_str == "") asar_throw_error(0, error_type_block, error_id_broken_incbin);
2277
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 start = getnum(start_str);
2278
5/6
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
108 if (foundlabel && !foundlabel_static) asar_throw_error(0, error_type_block, error_id_no_labels_here);
2279 90 string end_str(split+2);
2280
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
90 if(end_str == "") asar_throw_error(0, error_type_block, error_id_broken_incbin);
2281
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 end = getnum(end_str);
2282
5/6
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
90 if (foundlabel && !foundlabel_static) asar_throw_error(0, error_type_block, error_id_no_labels_here);
2283 126 }
2284
1/2
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
180 const char* current_file = get_current_file_name();
2285 90 string name;
2286 // RPG Hacker: Should this also throw on absolute paths?
2287 // E.g., on something starting with C:/ or whatever.
2288
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 162 times.
180 if (strchr(par, '\\'))
2289 {
2290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 asar_throw_error(0, error_type_block, error_id_platform_paths);
2291 }
2292
1/2
✓ Branch 0 taken 162 times.
✗ Branch 1 not taken.
162 name = safedequote(par);
2293 char * data;//I couldn't find a way to get this into an autoptr
2294
6/10
✓ Branch 0 taken 162 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 126 times.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 36 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 36 times.
162 if (!readfile(name, current_file, &data, &len)) asar_throw_error(0, error_type_block, vfile_error_to_error_id(asar_get_last_io_error()), name.data());
2295
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 72 times.
126 autoptr<char*> datacopy=data;
2296
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 72 times.
126 if (!end) end=len;
2297
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
126 if(start < 0) asar_throw_error(0, error_type_block, error_id_file_offset_out_of_bounds, dec(start).data(), name.data());
2298
3/8
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 126 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
126 if (end < start || end > len || end < 0) asar_throw_error(0, error_type_block, error_id_file_offset_out_of_bounds, dec(end).data(), name.data());
2299
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 108 times.
126 if (numwords==4)
2300 {
2301
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 asar_throw_warning(0, warning_id_feature_deprecated, "incbin with target location", "put an org before the incbin");
2302
2/5
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
18 if (!confirmname(word[3]))
2303 {
2304 int pos=(int)getnum(word[3]);
2305 if (foundlabel && !foundlabel_static) asar_throw_error(0, error_type_block, error_id_no_labels_here);
2306 int offset=snestopc(pos);
2307 if (offset + end - start > 0xFFFFFF) asar_throw_error(0, error_type_block, error_id_16mb_rom_limit);
2308 if (offset+end-start>romlen) romlen=offset+end-start;
2309 if (pass==2)
2310 {
2311 writeromdata(offset, data+start, end-start);
2312 add_addr_to_line(pos);
2313 }
2314 else if(pass == 1) addromwrite(offset, end-start);
2315 }
2316 else
2317 {
2318 int pos;
2319
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if (pass==0)
2320 {
2321 // TODO: this shouldn't allocate in pass 0 actually
2322 // and needs an addromwrite probably......
2323 // actually it should just use the freespace finder at the end of pass 1
2324
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 if (end - start > 65536) asar_throw_error(0, error_type_block, error_id_incbin_64kb_limit);
2325
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 pos=getpcfreespace(end-start, -1, true, false);
2326
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 if (pos < 0) asar_throw_error(0, error_type_block, error_id_no_freespace, dec(end - start).data());
2327 6 int foundfreespaceid=getfreespaceid();
2328 6 freespaces[foundfreespaceid].dont_find = true;
2329 6 freespaces[foundfreespaceid].pos = pctosnes(pos);
2330
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 setlabel(word[3], freespaces[foundfreespaceid].pos, false, foundfreespaceid);
2331 // is this necessary?
2332
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 writeromdata_bytes(pos, 0xFF, end-start);
2333 }
2334
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if (pass==1)
2335 {
2336 6 getfreespaceid();//nothing to do here, but we want to tick the counter
2337 }
2338
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if (pass==2)
2339 {
2340 6 int foundfreespaceid =getfreespaceid();
2341
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 if (freespaces[foundfreespaceid].leaked) asar_throw_warning(2, warning_id_freespace_leaked);
2342
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
6 writeromdata(snestopc(freespaces[foundfreespaceid].pos&0xFFFFFF), data+start, end-start);
2343
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 add_addr_to_line((freespaces[foundfreespaceid].pos&0xFFFFFF) - 8);
2344 6 freespaceuse+=8+end-start;
2345 }
2346 }
2347 }
2348 else
2349 {
2350
3/4
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 198 times.
✓ Branch 3 taken 108 times.
306 for (int i=start;i<end;i++) write1((unsigned int)data[i]);
2351
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 add_addr_to_line(addrToLinePos);
2352 }
2353 180 }
2354
4/4
✓ Branch 0 taken 2061 times.
✓ Branch 1 taken 1764 times.
✓ Branch 2 taken 1845 times.
✓ Branch 3 taken 216 times.
3825 else if (is("skip") || is("fill"))
2355 {
2356
3/6
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1962 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1980 if(numwords != 2 && numwords != 3 && numwords != 5) asar_throw_error(0, error_type_block, error_id_unknown_command);
2357
5/8
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1962 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1980 if(numwords > 2 && stricmp(word[1], "align")) asar_throw_error(0, error_type_block, error_id_unknown_command);
2358
5/8
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1962 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1980 if(numwords == 5 && stricmp(word[3], "offset")) asar_throw_error(0, error_type_block, error_id_unknown_command);
2359 int amount;
2360
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1962 times.
1980 if(numwords > 2)
2361 {
2362
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 int alignment = getnum(word[2]);
2363
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
18 if(foundlabel && !foundlabel_static) asar_throw_error(0, error_type_block, error_id_no_labels_here);
2364 int offset = 0;
2365
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if(numwords==5)
2366 {
2367
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 offset = getnum(word[4]);
2368
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
18 if(foundlabel && !foundlabel_static) asar_throw_error(0, error_type_block, error_id_no_labels_here);
2369 }
2370
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if(alignment > 0x800000) asar_throw_error(0, error_type_block, error_id_alignment_too_big);
2371
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if(alignment < 1) asar_throw_error(0, error_type_block, error_id_alignment_too_small);
2372
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if(alignment & (alignment-1)) asar_throw_error(0, error_type_block, error_id_invalid_alignment);
2373 // i just guessed this formula but it seems to work
2374 18 amount = (alignment - ((snespos - offset) & (alignment-1))) & (alignment-1);
2375 }
2376 else
2377 {
2378
1/2
✓ Branch 0 taken 1962 times.
✗ Branch 1 not taken.
1962 amount = (int)getnum(par);
2379
5/6
✓ Branch 0 taken 1926 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
1962 if (foundlabel && !foundlabel_static) asar_throw_error(0, error_type_block, error_id_no_labels_here);
2380 }
2381
2/2
✓ Branch 0 taken 1764 times.
✓ Branch 1 taken 198 times.
1962 if(is("skip")) step(amount);
2382 else
2383 {
2384
3/4
✓ Branch 0 taken 1221210 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1221210 times.
✓ Branch 3 taken 198 times.
1221408 for(int i=0; i < amount; i++) write1(fillbyte[i%12]);
2385
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 add_addr_to_line(addrToLinePos);
2386 }
2387
2388 }
2389
4/4
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 1536 times.
✓ Branch 2 taken 291 times.
✓ Branch 3 taken 18 times.
1845 else if (is0("cleartable"))
2390 {
2391
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 cleartable();
2392 }
2393
4/4
✓ Branch 0 taken 291 times.
✓ Branch 1 taken 1536 times.
✓ Branch 2 taken 273 times.
✓ Branch 3 taken 18 times.
1827 else if (is0("pushtable"))
2394 {
2395
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 tablestack.append(thetable);
2396 }
2397
4/4
✓ Branch 0 taken 273 times.
✓ Branch 1 taken 1536 times.
✓ Branch 2 taken 255 times.
✓ Branch 3 taken 18 times.
1809 else if (is0("pulltable"))
2398 {
2399
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if (tablestack.count <= 0) asar_throw_error(0, error_type_block, error_id_pulltable_without_table);
2400
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 thetable=tablestack[tablestack.count-1];
2401
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 tablestack.remove(tablestack.count-1);
2402 }
2403
3/4
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 1683 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 108 times.
1791 else if (is("function") && numwords >= 3)
2404 {
2405
3/6
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
108 if (stricmp(word[2], "=")) asar_throw_error(0, error_type_block, error_id_broken_function_declaration);
2406
2/6
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 108 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
108 if (!confirmqpar(word[1])) asar_throw_error(0, error_type_block, error_id_broken_function_declaration);
2407 108 string line=word[1];
2408
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 line.qnormalize();
2409 108 char * startpar=strqchr(line.data(), '(');
2410
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
108 if (!startpar) asar_throw_error(0, error_type_block, error_id_broken_function_declaration);
2411 108 *startpar=0;
2412
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
108 startpar++;
2413
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
108 if (!confirmname(line)) asar_throw_error(0, error_type_block, error_id_invalid_function_name);
2414 108 char * endpar=strqchr(startpar, ')');
2415 //confirmqpar requires that all parentheses are matched, and a starting one exists, therefore it is harmless to not check for nulls
2416
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
108 if (endpar[1]) asar_throw_error(0, error_type_block, error_id_broken_function_declaration);
2417 108 *endpar=0;
2418
2419 54 string pars;
2420
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 108 times.
216 for(int i = 3; i < numwords; i++){
2421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if(i > 3) pars += " ";
2422 108 pars += word[i];
2423 }
2424
2425
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 createuserfunc(line, startpar, pars.data());
2426 108 }
2427
4/4
✓ Branch 0 taken 1428 times.
✓ Branch 1 taken 255 times.
✓ Branch 2 taken 558 times.
✓ Branch 3 taken 870 times.
1683 else if (is1("print"))
2428 {
2429
2/2
✓ Branch 0 taken 852 times.
✓ Branch 1 taken 18 times.
870 string out = handle_print(par);
2430
3/4
✓ Branch 0 taken 284 times.
✓ Branch 1 taken 568 times.
✓ Branch 2 taken 284 times.
✗ Branch 3 not taken.
852 if (pass==2) print(out);
2431 852 }
2432
4/4
✓ Branch 0 taken 558 times.
✓ Branch 1 taken 255 times.
✓ Branch 2 taken 540 times.
✓ Branch 3 taken 18 times.
813 else if (is1("reset"))
2433 {
2434 if(0);
2435
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
18 else if (!stricmp(par, "bytes")) bytes=0;
2436 else if (!stricmp(par, "freespaceuse")) freespaceuse=0;
2437 else asar_throw_error(2, error_type_block, error_id_unknown_variable);
2438 }
2439
13/16
✓ Branch 0 taken 540 times.
✓ Branch 1 taken 255 times.
✓ Branch 2 taken 486 times.
✓ Branch 3 taken 54 times.
✓ Branch 4 taken 486 times.
✓ Branch 5 taken 255 times.
✓ Branch 6 taken 486 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 486 times.
✓ Branch 9 taken 255 times.
✓ Branch 10 taken 486 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 486 times.
✓ Branch 13 taken 255 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 486 times.
795 else if (is1("padbyte") || is1("padword") || is1("padlong") || is1("paddword"))
2440 {
2441 int len = 0;
2442
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 if (is("padbyte")) len=1;
2443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (is("padword")) len=2;
2444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (is("padlong")) len=3;
2445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (is("paddword")) len=4;
2446
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 unsigned int val=getnum(par);
2447
5/6
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
54 if (foundlabel && !foundlabel_static) asar_throw_error(0, error_type_block, error_id_no_labels_here);
2448
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 36 times.
468 for (int i=0;i<12;i+=len)
2449 {
2450 unsigned int tmpval=val;
2451
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 432 times.
864 for (int j=0;j<len;j++)
2452 {
2453 432 padbyte[i+j]=(unsigned char)tmpval;
2454 432 tmpval>>=8;
2455 }
2456 }
2457 }
2458
4/4
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 255 times.
✓ Branch 2 taken 432 times.
✓ Branch 3 taken 54 times.
741 else if (is1("pad"))
2459 {
2460
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
54 if (freespaceid > 0) asar_throw_error(0, error_type_block, error_id_pad_in_freespace);
2461
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 int num=(int)getnum(par);
2462
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
54 if ((unsigned int)num & 0xFF000000) asar_throw_error(0, error_type_block, error_id_snes_address_doesnt_map_to_rom, hex((unsigned int)num, 6).data());
2463
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 18 times.
54 if (num>realsnespos)
2464 {
2465
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 int end=snestopc(num);
2466
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 int start=snestopc(realsnespos);
2467 36 int len=end-start;
2468
3/4
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 180 times.
✓ Branch 3 taken 36 times.
216 for (int i=0;i<len;i++) write1(padbyte[i%12]);
2469
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 add_addr_to_line(addrToLinePos);
2470 }
2471 }
2472
16/16
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 255 times.
✓ Branch 2 taken 342 times.
✓ Branch 3 taken 90 times.
✓ Branch 4 taken 342 times.
✓ Branch 5 taken 255 times.
✓ Branch 6 taken 324 times.
✓ Branch 7 taken 18 times.
✓ Branch 8 taken 324 times.
✓ Branch 9 taken 255 times.
✓ Branch 10 taken 306 times.
✓ Branch 11 taken 18 times.
✓ Branch 12 taken 306 times.
✓ Branch 13 taken 255 times.
✓ Branch 14 taken 18 times.
✓ Branch 15 taken 288 times.
687 else if (is1("fillbyte") || is1("fillword") || is1("filllong") || is1("filldword"))
2473 {
2474 int len = 0;
2475
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 54 times.
144 if (is("fillbyte")) len=1;
2476
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 126 times.
144 if (is("fillword")) len=2;
2477
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 126 times.
144 if (is("filllong")) len=3;
2478
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 126 times.
144 if (is("filldword")) len=4;
2479
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 unsigned int val= getnum(par);
2480
5/6
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 108 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
144 if (foundlabel && !foundlabel_static) asar_throw_error(0, error_type_block, error_id_no_labels_here);
2481
2/2
✓ Branch 0 taken 1098 times.
✓ Branch 1 taken 126 times.
1224 for (int i=0;i<12;i+=len)
2482 {
2483 unsigned int tmpval=val;
2484
2/2
✓ Branch 0 taken 1512 times.
✓ Branch 1 taken 1098 times.
2610 for (int j=0;j<len;j++)
2485 {
2486 1512 fillbyte[i+j]=(unsigned char)tmpval;
2487 1512 tmpval>>=8;
2488 }
2489 }
2490 }
2491
3/4
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 255 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 288 times.
543 else if (is1("arch"))
2492 {
2493
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 288 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
288 if(in_spcblock) asar_throw_error(0, error_type_block, error_id_feature_unavaliable_in_spcblock);
2494
4/4
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 108 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 108 times.
288 if (!stricmp(par, "65816")) { arch=arch_65816; return; }
2495
4/4
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 36 times.
216 if (!stricmp(par, "spc700")) { arch=arch_spc700; return; }
2496
2/4
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
72 if (!stricmp(par, "superfx")) { arch=arch_superfx; return; }
2497 asar_throw_error(0, error_type_block, error_id_broken_command, "arch", "Invalid architecture, expected one of 65816, spc700, superfx");
2498 }
2499
6/8
✓ Branch 0 taken 255 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 147 times.
✓ Branch 3 taken 108 times.
✓ Branch 4 taken 147 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 39 times.
✓ Branch 7 taken 108 times.
255 else if (is0("{") || is0("}")) {}
2500 else
2501 {
2502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 asar_throw_error(1, error_type_block, error_id_unknown_command);
2503 }
2504
2505 185238 }
2506
2507 41619 bool assemblemapper(char** word, int numwords)
2508 {
2509 41619 auto previous_mapper = mapper;
2510 if(0);
2511
4/4
✓ Branch 0 taken 2397 times.
✓ Branch 1 taken 39222 times.
✓ Branch 2 taken 291 times.
✓ Branch 3 taken 2106 times.
41619 else if (is0("lorom"))
2512 {
2513 //this also makes xkas set snespos to $008000 for some reason
2514 291 mapper=lorom;
2515 }
2516
4/4
✓ Branch 0 taken 2106 times.
✓ Branch 1 taken 39222 times.
✓ Branch 2 taken 1983 times.
✓ Branch 3 taken 123 times.
41328 else if (is0("hirom"))
2517 {
2518 //xkas makes this point to $C00000
2519 123 mapper=hirom;
2520 }
2521
4/4
✓ Branch 0 taken 1983 times.
✓ Branch 1 taken 39222 times.
✓ Branch 2 taken 1962 times.
✓ Branch 3 taken 21 times.
41205 else if (is0("exlorom"))
2522 {
2523 21 mapper = exlorom;
2524 }
2525
4/4
✓ Branch 0 taken 1962 times.
✓ Branch 1 taken 39222 times.
✓ Branch 2 taken 1941 times.
✓ Branch 3 taken 21 times.
41184 else if (is0("exhirom"))
2526 {
2527 21 mapper=exhirom;
2528 }
2529
4/4
✓ Branch 0 taken 1941 times.
✓ Branch 1 taken 39222 times.
✓ Branch 2 taken 1902 times.
✓ Branch 3 taken 39 times.
41163 else if (is0("sfxrom"))
2530 {
2531 39 mapper=sfxrom;
2532 //fastrom=false;
2533 }
2534
4/4
✓ Branch 0 taken 1902 times.
✓ Branch 1 taken 39222 times.
✓ Branch 2 taken 1788 times.
✓ Branch 3 taken 114 times.
41124 else if (is0("norom"))
2535 {
2536 //$000000 would be the best snespos for this, but I don't care
2537 114 mapper=norom;
2538 //fastrom=false;
2539
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 36 times.
114 if(!force_checksum_fix)
2540 78 checksum_fix_enabled = false;//we don't know where the header is, so don't set the checksum
2541 }
2542
4/4
✓ Branch 0 taken 1788 times.
✓ Branch 1 taken 39222 times.
✓ Branch 2 taken 1767 times.
✓ Branch 3 taken 21 times.
41010 else if (is0("fullsa1rom"))
2543 {
2544 21 mapper=bigsa1rom;
2545 //fastrom=false;
2546 }
2547
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 40914 times.
40989 else if (is("sa1rom"))
2548 {
2549 //fastrom=false;
2550
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 if (par)
2551 {
2552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (word[2]) asar_throw_error(0, error_type_block, error_id_invalid_mapper);
2553
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if (!is_digit(par[0]) || par[1]!=',' ||
2554
2/4
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
57 !is_digit(par[2]) || par[3]!=',' ||
2555
2/4
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
57 !is_digit(par[4]) || par[5]!=',' ||
2556
3/6
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 57 times.
114 !is_digit(par[6]) || par[7]) asar_throw_error(0, error_type_block, error_id_invalid_mapper);
2557 int len;
2558 57 autoptr<char**> pars=qpsplit(par, ',', &len);
2559
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 verify_paren(pars);
2560
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
57 if (len!=4) asar_throw_error(0, error_type_block, error_id_invalid_mapper);
2561 57 sa1banks[0]=(par[0]-'0')<<20;
2562 57 sa1banks[1]=(par[2]-'0')<<20;
2563 57 sa1banks[4]=(par[4]-'0')<<20;
2564 57 sa1banks[5]=(par[6]-'0')<<20;
2565 57 }
2566 else
2567 {
2568 18 sa1banks[0]=0<<20;
2569 18 sa1banks[1]=1<<20;
2570 18 sa1banks[4]=2<<20;
2571 18 sa1banks[5]=3<<20;
2572 }
2573 75 mapper=sa1rom;
2574 }
2575 else return false;
2576
2577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 705 times.
705 if(in_spcblock) asar_throw_error(0, error_type_block, error_id_feature_unavaliable_in_spcblock);
2578
2/2
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 270 times.
705 if(!mapper_set){
2579 435 mapper_set = true;
2580
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 234 times.
270 }else if(previous_mapper != mapper){
2581 234 asar_throw_warning(1, warning_id_mapper_already_set);
2582 }
2583 return true;
2584 }
2585