Mercurial > hg > forks > dxa
annotate main.c @ 15:89183953bddc
Delete trailing whitespace.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 14 Oct 2021 01:40:24 +0300 |
parents | 84c0facfc43c |
children | a2a81589380d |
rev | line source |
---|---|
0 | 1 /*\ |
5
b91c47026822
Make version information a compile-time define.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
2 * dxa -- symbolic 65xx disassembler |
0 | 3 * |
4 * Based on d65 Copyright (C) 1993, 1994 Marko M\"akel\"a | |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
5 * Changes for dxa (C) 2005-2019 Cameron Kaiser |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
6 * Modifications for ++ version (c) 2015-2021 Matti 'ccr' Hamalainen <ccr@tnsp.org> |
0 | 7 * |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
21 * | |
22 * Marko does not maintain dxa, so questions specific to dxa should be | |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
23 * sent to me at ckaiser@floodgap.com. |
0 | 24 * |
25 \*/ | |
26 | |
27 #define _MAIN_C_ | |
28 #include <stdio.h> | |
29 #include <stdlib.h> | |
30 #include <string.h> | |
31 #ifdef __GNUC__ | |
32 #include <unistd.h> | |
33 #endif | |
34 #ifdef LONG_OPTIONS | |
35 #include <getopt.h> | |
36 #endif /* __GNUC__ */ | |
37 #include "proto.h" | |
38 #include "options.h" | |
39 #include "opcodes.h" | |
40 | |
2
ec2f8f6f1dc9
Cleanup pass #1: Get rid of some ancient K&R-isms.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
41 |
0 | 42 int main (int argc, char **argv) |
43 { | |
44 FILE *file; | |
45 unsigned address1, address2; | |
46 #ifdef LONG_OPTIONS | |
47 int option_index; | |
48 #endif | |
49 int fFinished = FALSE, fType; | |
50 char labelname[MAXLINE], strig[MAXLINE], *scanner; | |
51 | |
52 extern char *optarg; | |
53 extern int optind; | |
54 | |
55 #ifdef LONG_OPTIONS | |
56 static struct option cmd_options [] = { | |
57 { "datablock", 1, 0, 'b' }, /* an address range to be marked | |
58 as a data block */ | |
59 { "datablocks", 1, 0, 'B' },/* a file containing the address ranges | |
60 to be marked as data blocks */ | |
61 { "labels", 1, 0, 'l' }, /* a file containing labels to be translated | |
62 in the output phase */ | |
63 { "routine", 1, 0, 'r' }, /* an address of a routine */ | |
64 { "routines", 1, 0, 'R' }, /* a file containing the addresses */ | |
65 | |
66 { "listing-width", 1, 0, 'L' }, | |
67 /* maximum number of dumped bytes per line */ | |
68 { "addresses", 1, 0, 'a' }, /* dumping addresses in the output phase */ | |
69 { "datablock-detection", 1, 0, 'd' }, | |
70 /* data block detection options */ | |
71 { "processor", 1, 0, 'p' }, /* instruction set */ | |
72 { "no-colon-newline", 0, 0, 'n' }, | |
73 { "colon-newline", 0, 0, 'N' }, | |
74 { "no-external-labels", 0, 0, 'e' }, | |
75 { "external-labels", 0, 0, 'E' }, | |
76 { "address-tables", 0, 0, 't' }, | |
77 { "no-address-statements", 0, 0, 's' }, | |
78 { "address-statements", 0, 0, 'S' }, | |
79 { "suspect-jsr", 0, 0, 'J' }, | |
80 { "no-suspect-jsr", 0, 0, 'j' }, | |
81 { "one-byte-routines", 0, 0, 'O' }, | |
82 { "no-one-byte-routines", 0, 0, 'o' }, | |
83 { "stupid-jumps", 0, 0, 'M' }, | |
84 { "no-stupid-jumps", 0, 0, 'm' }, | |
85 { "allow-brk", 0, 0, 'W' }, | |
86 { "no-allow-brk", 0, 0, 'w' }, | |
87 { "suspect-branches", 0, 0, 'C' }, | |
88 { "no-suspect-branches", 0, 0, 'c' }, | |
89 { "cross-reference", 0, 0, 'X' }, | |
90 { "no-cross-reference", 0, 0, 'x' }, | |
91 { "verbose", 0, 0, 'v' }, | |
92 { "help", 0, 0, '?' }, | |
93 { "word-sa", 0, 0, 'Q' }, | |
94 { "no-word-sa", 0, 0, 'q' }, | |
95 { "get-sa", 0, 0, 'G' }, | |
96 { "no-get-sa", 0, 0, 'g' }, | |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
97 { "detect-basic", 0, 0, 'U' }, |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
98 { "no-detect-basic", 0, 0, 'u' }, |
0 | 99 { NULL, 0, 0, 0 } |
100 }; | |
101 #endif /* LONG_OPTIONS */ | |
102 | |
103 opset = standard_nmos6502; | |
104 | |
105 StartAddress = 0; | |
106 Options = O_ADR_ADR_DMP | B_LBL_ALWAYS | O_TBL_NOEXT | | |
107 B_STM_DETECT | B_STK_BALANCE | B_RSC_STRICT | O_DBL_STRICT | | |
108 B_JMP_STRICT | B_BRK_REJECT; | |
109 | |
110 /* dxa defaults */ | |
111 Options = (Options & ~M_ADDRESSES) | O_ADR_NOTHING; | |
112 Options = (Options & ~M_DATA_BLOCKS) | O_DBL_IGNORE; | |
113 Options &= ~B_LBL_ALWAYS; | |
114 Options &= ~B_LABCOL; | |
115 Options |= B_SA_WORD; | |
116 Options |= B_GET_SA; | |
117 | |
118 for (address1 = sizeof MemType / sizeof *MemType; address1--; | |
119 MemType[address1] = 0); | |
120 | |
121 for (address1 = sizeof MemFlag / sizeof *MemFlag; address1--; | |
122 MemFlag[address1] = MemLabel[address1] = 0); | |
123 | |
124 for (address1 = sizeof LowByte / sizeof *LowByte; address1--; | |
125 HighByte[address1] = LowByte[address1] = 0); | |
126 | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
6
diff
changeset
|
127 for (address1 = sizeof MemReferenced / sizeof *MemReferenced; address1--; |
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
6
diff
changeset
|
128 MemReferenced[address1] = 0); |
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
6
diff
changeset
|
129 |
0 | 130 for (prog = *argv; *prog; prog++); |
131 for (;prog > *argv; prog--) | |
132 if (*prog == '/') { | |
133 prog++; | |
134 break; | |
135 } | |
136 | |
137 while (!fFinished) | |
138 #ifdef LONG_OPTIONS | |
139 switch (getopt_long (argc, argv, | |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
140 "?b:B:L:r:R:h:l:a:d:p:g:t:eEnNsSjJoOcCmMvVwWxXqQGuU", |
0 | 141 cmd_options, &option_index)) { |
142 #else | |
143 switch (getopt (argc, argv, | |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
144 "?b:B:L:r:R:h:l:a:d:p:g:t:eEnNsSjJoOcCmMvVwWxXqQGuU")){ |
0 | 145 #endif /* LONG_OPTIONS */ |
146 case -1: | |
147 case ':': | |
148 fFinished = TRUE; | |
149 break; | |
150 | |
151 case '?': | |
152 case 'V': | |
153 goto Usage; | |
154 | |
155 case 'b': | |
156 if (*optarg == '!') { | |
157 fType = MEM_PARAMETER; | |
158 optarg++; | |
159 } | |
160 else if (*optarg == '?') { | |
161 fType = MEM_UNPROCESSED; | |
162 optarg++; | |
163 } | |
164 else | |
165 fType = MEM_DATA; | |
166 | |
167 if (!sscanf (optarg, "%X-%X", &address1, &address2) || | |
168 address1 > 65535 || address2 > 65535) { | |
169 fprintf (stderr, "%s: Error in data block address range `%s'.\n\n", | |
170 prog, optarg); | |
171 goto Usage; | |
172 } | |
173 | |
174 for (; (ADDR_T)address1 != address2; address1++) { | |
175 SetMemType (address1, fType); | |
176 SetMemFlag (address1); | |
177 } | |
178 | |
179 SetMemType (address1, fType); | |
180 SetMemFlag (address1); | |
181 | |
182 break; | |
183 | |
184 case 'B': | |
185 if (!((file = fopen (optarg, "rt")))) { | |
186 fprintf (stderr, "%s: Could not open %s.\n", prog, optarg); | |
187 return 2; | |
188 } | |
189 | |
190 while (!feof (file)) { | |
191 if ('!' == (fType = fgetc (file))) | |
192 fType = MEM_PARAMETER; | |
193 else if ('?' == fType) | |
194 fType = MEM_UNPROCESSED; | |
195 else { | |
196 ungetc (fType, file); | |
197 fType = MEM_DATA; | |
198 } | |
199 | |
200 if (!fscanf (file, "%X-%X\n", &address1, &address2) || | |
201 address1 > 65535 || address2 > 65535) { | |
202 fprintf (stderr, "%s: Error in data block address file %s.\n", | |
203 prog, optarg); | |
204 | |
205 fclose (file); | |
206 return 3; | |
207 } | |
208 | |
209 for (; (ADDR_T)address1 != address2; address1++) { | |
210 SetMemType (address1, fType); | |
211 SetMemFlag (address1); | |
212 } | |
213 | |
214 SetMemType (address1, fType); | |
215 SetMemFlag (address1); | |
216 } | |
217 | |
218 fclose (file); | |
219 break; | |
220 | |
221 case 'r': | |
222 if (!sscanf (optarg, "%X", &address1) || address1 > 65535) { | |
223 fprintf (stderr, "%s: Error in routine address `%s'.\n\n", | |
224 prog, optarg); | |
225 goto Usage; | |
226 } | |
227 | |
228 AddEntry (address1, address1, RTN_SURE); | |
229 break; | |
230 | |
231 case 'R': | |
232 if (!((file = fopen (optarg, "rt")))) { | |
233 fprintf (stderr, "%s: Could not open %s.\n", prog, optarg); | |
234 return 2; | |
235 } | |
236 | |
237 while (!feof (file)) { | |
238 if (!fscanf (file, "%X\n", &address1) || address1 > 65535) { | |
239 fprintf (stderr, "%s: Error in data block address file `%s'.\n", | |
240 prog, optarg); | |
241 | |
242 fclose (file); | |
243 return 3; | |
244 } | |
245 | |
246 AddEntry (address1, address1, RTN_SURE); | |
247 } | |
248 | |
249 fclose (file); | |
250 break; | |
251 | |
252 case 'L': | |
253 if (0 > (listwidth = atoi (optarg))) { | |
254 fprintf (stderr, "%s: Illegal listing width specified.\n\n", prog); | |
255 goto Usage; | |
256 } | |
257 | |
258 break; | |
259 | |
260 case 'a': | |
261 if (!strcmp (optarg, "disabled")) | |
262 Options = (Options & ~M_ADDRESSES) | O_ADR_NOTHING; | |
263 else if (!strcmp (optarg, "enabled")) | |
264 Options = (Options & ~M_ADDRESSES) | O_ADR_ADRPFIX; | |
265 else if (!strcmp (optarg, "dump")) | |
266 Options = (Options & ~M_ADDRESSES) | O_ADR_ADR_DMP; | |
267 else { | |
268 fprintf (stderr, "%s: Unrecognized option for dumping addresses.\n\n", | |
269 prog); | |
270 goto Usage; | |
271 } | |
272 break; | |
273 | |
274 case 'd': | |
275 if (!strcmp (optarg, "poor")) | |
276 Options = (Options & ~M_DATA_BLOCKS) | O_DBL_IGNORE; | |
277 else if (!strcmp (optarg, "extended")) | |
278 Options = (Options & ~M_DATA_BLOCKS) | O_DBL_DETECT; | |
279 else if (!strcmp (optarg, "skip-scanning")) | |
280 Options = (Options & ~M_DATA_BLOCKS) | O_DBL_NOSCAN; | |
281 else if (!strcmp (optarg, "strict")) | |
282 Options = (Options & ~M_DATA_BLOCKS) | O_DBL_STRICT; | |
283 else { | |
284 fprintf (stderr, | |
285 "%s: Unrecognized option for detecting data blocks.\n\n", | |
286 prog); | |
287 goto Usage; | |
288 } | |
289 break; | |
290 | |
291 case 'p': | |
292 if (!strcmp (optarg, "all-nmos6502")) | |
293 opset = all_nmos6502; | |
294 else if (!strcmp (optarg, "rational-nmos6502")) | |
295 opset = rational_nmos6502; | |
296 else if (!strcmp (optarg, "useful-nmos6502")) | |
297 opset = useful_nmos6502; | |
298 else if (!strcmp (optarg, "traditional-nmos6502")) | |
299 opset = traditional_nmos6502; | |
300 else if (!strcmp (optarg, "r65c02")) | |
301 opset = r65c02; | |
302 else if (!strcmp (optarg, "standard-nmos6502")) | |
303 opset = standard_nmos6502; | |
304 else { | |
305 fprintf (stderr, "%s: Unsupported instruction set `%s'.\n\n", | |
306 prog, optarg); | |
307 goto Usage; | |
308 } | |
309 break; | |
310 | |
311 case 'e': | |
312 Options &= ~B_LBL_ALWAYS; | |
313 break; | |
314 case 'E': | |
315 Options |= B_LBL_ALWAYS; | |
316 break; | |
317 | |
318 case 't': | |
319 if (!strcmp (optarg, "ignore")) | |
320 Options = (Options & ~M_ADR_TABLES) | O_TBL_IGNORE; | |
321 else if (!strcmp (optarg, "detect-all")) | |
322 Options = (Options & ~M_ADR_TABLES) | O_TBL_DETECT; | |
323 else if (!strcmp (optarg, "detect-internal")) | |
324 Options = (Options & ~M_ADR_TABLES) | O_TBL_NOEXT; | |
325 else { | |
326 fprintf (stderr, | |
327 "%s: Unknown address table detection option `%s'.\n\n", | |
328 prog, optarg); | |
329 goto Usage; | |
330 } | |
331 break; | |
332 | |
333 case 's': | |
334 Options &= ~B_STM_DETECT; | |
335 break; | |
336 case 'S': | |
337 Options |= B_STM_DETECT; | |
338 break; | |
339 | |
340 case 'J': | |
341 Options &= ~B_STK_BALANCE; | |
342 break; | |
343 case 'j': | |
344 Options |= B_STK_BALANCE; | |
345 break; | |
346 | |
347 case 'o': | |
348 Options &= ~B_RSC_STRICT; | |
349 break; | |
350 case 'O': | |
351 Options |= B_RSC_STRICT; | |
352 break; | |
353 | |
354 case 'c': | |
355 Options &= ~B_SCEPTIC; | |
356 break; | |
357 case 'C': | |
358 Options |= B_SCEPTIC; | |
359 break; | |
360 | |
361 case 'M': | |
362 Options &= ~B_JMP_STRICT; | |
363 break; | |
364 case 'm': | |
365 Options |= B_JMP_STRICT; | |
366 break; | |
367 | |
368 case 'v': | |
369 fVerbose = TRUE; | |
370 break; | |
371 | |
372 case 'W': | |
373 Options &= ~B_BRK_REJECT; | |
374 break; | |
375 case 'w': | |
376 Options |= B_BRK_REJECT; | |
377 break; | |
378 | |
379 case 'x': | |
380 Options &= ~B_CROSSREF; | |
381 break; | |
382 case 'X': | |
383 Options |= B_CROSSREF; | |
384 break; | |
385 | |
386 /* new or altered dxa options */ | |
387 case 'n': | |
388 Options &= ~B_LABCOL; | |
389 break; | |
390 case 'N': | |
391 Options |= B_LABCOL; | |
392 break; | |
393 case 'q': | |
394 Options &= ~B_SA_WORD; | |
395 break; | |
396 case 'Q': | |
397 Options |= B_SA_WORD; | |
398 break; | |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
399 case 'u': |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
400 Options &= ~B_DETECT_BASIC; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
401 break; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
402 case 'U': |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
403 Options |= B_DETECT_BASIC; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
404 break; |
0 | 405 case 'G': |
406 Options |= B_GET_SA; | |
407 break; | |
408 case 'g': | |
409 Options &= ~B_GET_SA; | |
410 if (!sscanf (optarg, "%X", &address1) || address1 > 65535) { | |
411 fprintf (stderr, "%s: Error specifying starting address `%s'.\n\n", | |
412 prog, optarg); | |
413 goto Usage; | |
414 } | |
415 StartAddress = address1; | |
416 break; | |
417 case 'l': | |
418 if (!((file = fopen (optarg, "rt")))) { | |
419 fprintf (stderr, | |
420 "%s: Label file %s could not be opened for reading.\n\n", | |
421 prog, optarg); | |
422 | |
423 goto Usage; | |
424 } | |
425 | |
426 while (!feof (file)) { | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
427 int tmp; |
0 | 428 fType = fgetc (file); |
429 | |
430 if (feof (file)) | |
431 break; | |
432 | |
433 ungetc (fType, file); | |
434 | |
435 /* This is the xa-compatible label scanner. */ | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
436 if (!fscanf(file, "%s%i,%i,%i", labelname, &address1, &tmp, &address2) || |
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
437 address1 > 65535 || |
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
438 !fgets(strig, sizeof strig, file)) { |
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
439 |
0 | 440 LabelError: |
441 fprintf (stderr, "%s: Error in label file %s.\n", prog, optarg); | |
442 fprintf (stderr, "Address(?): 0x%x ... Label(?): \"%s\"\n\n", | |
443 address1, labelname); | |
444 fclose (file); | |
445 return 3; | |
446 } | |
447 | |
448 for (scanner = labelname; *scanner; scanner++); | |
449 | |
450 #if(0) | |
451 if (scanner[-1] != '\n') goto LabelError; /* line too long */ | |
452 #endif | |
453 | |
454 while (--scanner > labelname && ( | |
455 *(unsigned char *)scanner < 32 || | |
456 *(unsigned char *)scanner == 44)) /* and commas */ | |
457 *scanner = 0; /* remove trailing control characters */ | |
458 | |
459 for (scanner = labelname; *(unsigned char *)scanner < 32; scanner++) | |
460 if (!*scanner) goto LabelError; /* label name missing */ | |
461 | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
462 AddLabel (address1, scanner, address2 != 0, address2); |
0 | 463 } |
464 | |
465 fclose (file); | |
466 } | |
467 | |
468 if (argc - optind > 1) { | |
469 Usage: | |
5
b91c47026822
Make version information a compile-time define.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
470 fprintf (stderr, "dxa %s -- symbolic 65xx disassembler\n", DXA_VERSION); |
0 | 471 fprintf (stderr, "Based on d65 copyright (C) 1993-4 Marko M\"akel\"a\n"); |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
472 fprintf (stderr, "Changes for dxa copyright (c) 2006-19 Cameron Kaiser\n\n"); |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
473 fprintf (stderr, "Modifications for ++ version (c) 2015-2021 Matti 'ccr' Hamalainen <ccr@tnsp.org>\n\n"); |
0 | 474 fprintf (stderr, "Usage: %s [options] [filename]\n", prog); |
475 return 1; | |
476 } | |
477 | |
478 /* Fix, Need "rb" (binary mode) on Windows to avoid termintating on $1A */ | |
479 if (!(file = (argc - optind) ? fopen (argv[argc - 1], "rb") : stdin)) { | |
480 fprintf (stderr, "%s: Couldn't open input file.\n", prog); | |
481 return 2; | |
482 } | |
483 | |
484 if (Options & B_GET_SA) { | |
485 StartAddress = (unsigned)fgetc (file); | |
486 StartAddress |= (unsigned)fgetc (file) << 8; | |
487 } | |
488 | |
489 if (feof (file)) { | |
490 fprintf (stderr, "%s: Error reading the file.\n", prog); | |
491 return 3; | |
492 } | |
493 | |
494 /* this doesn't work so well */ | |
495 /* AddEntry (StartAddress, StartAddress, RTN_SURE); */ | |
496 EndAddress = StartAddress + fread (&Memory[StartAddress], sizeof (char), | |
497 65536 - StartAddress, file); | |
498 | |
499 if (!feof (file)) { | |
500 if ((EndAddress = fread (Memory, sizeof (char), StartAddress, file))) | |
501 fprintf (stderr, "%s: Warning: Input file caused an address overflow.\n", | |
502 prog); | |
503 | |
504 if (!feof (file)) { | |
505 fprintf (stderr, "%s: Error: Input file is longer than 64 kilobytes.\n", | |
506 prog); | |
507 fclose (file); | |
508 return 3; | |
509 } | |
510 } | |
511 | |
512 fclose (file); | |
513 | |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
514 BasicHeaderLength = 0; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
515 if ((Options & B_DETECT_BASIC) && ((EndAddress - StartAddress) > 11) && (0 || |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
516 StartAddress == 0x0401 || /* PET */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
517 StartAddress == 0x0801 || /* C64 */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
518 StartAddress == 0x1001 || /* VIC, 16, +4 */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
519 StartAddress == 0x1c01 || /* 128 */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
520 0)) { |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
521 /* If this file starts at a typical BASIC starting address, try to mark |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
522 that as data. Bonus points for turning SYS xxxx into an entry point. |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
523 For example, 1010 SYS 2061 comes out like this: |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
524 .byt $0b,$08,$0a |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
525 .byt $0a,$9e,$32 |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
526 .byt $30,$36,$31 |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
527 .byt $00,$00,$00 |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
528 */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
529 |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
530 /* Heuristic: try to validate the line link address. If it seems sane, |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
531 process further. */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
532 ADDR_T ll = Memory[StartAddress] + (Memory[StartAddress+1] << 8); |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
533 if ((ll > StartAddress) && (ll < EndAddress - 2) && Memory[ll] == 0) { |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
534 ADDR_T offs = StartAddress + 5; /* byte after presumed first token */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
535 ADDR_T val = 0; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
536 ADDR_T i = 0; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
537 int ok = 0; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
538 |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
539 /* See if there is an encoded SYS address in the first line. */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
540 if (Memory[StartAddress+4] == 0x9e /* SYS */) { |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
541 for(; offs < StartAddress + 11; offs++) { /* stop overrun */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
542 if (Memory[offs] == 0x00) { |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
543 ok = 1; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
544 break; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
545 } |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
546 if (Memory[offs] == 32) /* space */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
547 continue; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
548 if (Memory[offs] < 48 || Memory[offs] > 57) { |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
549 ok = 0; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
550 break; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
551 } |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
552 if (val > 6553 || (val == 6553 && Memory[offs] > 53)) { |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
553 ok = 0; /* imminent overflow */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
554 break; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
555 } |
15 | 556 val = (val * 10) + (Memory[offs] - 48); |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
557 } |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
558 |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
559 if (ok && val > StartAddress && val < EndAddress) { |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
560 /* Address validates; mark it as an entry point. */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
561 AddEntry (val, val, RTN_SURE); |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
562 if (fVerbose) |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
563 fprintf(stderr, "%s: SYS %d found, marking as entry point\n", prog, val); |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
564 } |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
565 } |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
566 |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
567 /* Try to find the end of BASIC text. Three nulls needed. */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
568 ok = 0; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
569 for(; offs < EndAddress; offs++) { |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
570 if (Memory[offs] == 0) { |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
571 ok++; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
572 if (ok == 3) { |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
573 BasicHeaderLength = (offs - StartAddress) + 1; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
574 |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
575 /* Mark entire length of BASIC text as dead. */ |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
576 for(i = StartAddress; i < offs; i++) { |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
577 SetMemType(i, MEM_UNPROCESSED); |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
578 SetMemFlag(i); |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
579 } |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
580 if (fVerbose) |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
581 fprintf(stderr, "%s: BASIC text marked as dead through $%04x\n", prog, offs); |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
582 break; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
583 } else |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
584 continue; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
585 } |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
586 ok = 0; |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
587 } |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
588 if (ok < 3 && fVerbose) |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
589 fprintf(stderr, "%s: warning: couldn't find a valid end of BASIC text\n", prog); |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
590 |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
591 } else if (fVerbose) |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
592 fprintf(stderr, "%s: warning: BASIC starting address $%04x, but invalid line\n", |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
593 prog, StartAddress); |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
594 |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
595 } |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
596 |
0 | 597 if (fVerbose) |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
598 fprintf (stderr, "%s: disassembling $%04x-$%04x\n", prog, |
0 | 599 StartAddress, EndAddress); |
600 | |
601 if (ScanSpecified ()) { | |
602 fprintf (stderr, "\n%s: Invalid routine address(es) specified. Stop.\n", | |
603 prog); | |
604 | |
605 return 4; | |
606 } | |
607 | |
608 ScanPotentials (); | |
609 ScanTheRest (); | |
610 Collect (); | |
611 SearchVectors (); | |
612 Dump (); | |
613 | |
614 return 0; | |
615 } |