aboutsummaryrefslogtreecommitdiff
path: root/bas.c
diff options
context:
space:
mode:
Diffstat (limited to 'bas.c')
-rw-r--r--bas.c91
1 files changed, 83 insertions, 8 deletions
diff --git a/bas.c b/bas.c
index 64c4f3f..230032c 100644
--- a/bas.c
+++ b/bas.c
@@ -27,24 +27,50 @@ const char *self;
unsigned char program[BUFSIZE];
FILE *input_file;
FILE *output_file;
+char *output_filename = NULL;
void die(const char *msg) {
fprintf(stderr, "%s: %s\n", self, msg);
exit(1);
}
+void parse_general_args(int argc, char **argv, void (*helpfunc)()) {
+ if(argc < 2) {
+ (*helpfunc)();
+ exit(1);
+ }
+
+ if(strcmp(argv[1], "--help") == 0) {
+ (*helpfunc)();
+ exit(0);
+ }
+
+ if(strcmp(argv[1], "--version") == 0) {
+ printf("%s %s\n", self, VERSION);
+ exit(0);
+ }
+}
+
/* read entire file into memory */
-int readfile(void) {
- int got = fread(program, 1, BUFSIZE - 1, input_file);
- if(verbose) fprintf(stderr, "Read %d bytes.\n", got);
+void readfile(void) {
+ filelen = fread(program, 1, BUFSIZE - 1, input_file);
+ if(verbose) fprintf(stderr, "Read %d bytes.\n", filelen);
if(!feof(input_file))
fprintf(stderr, "Warning: file is >64KB, way too big for a BASIC program.\n");
- else if(got > MAX_PROG_SIZE)
- fprintf(stderr, "Warning: file is %d bytes, suspiciously large for a BASIC program.\n", got);
+ else if(filelen > MAX_PROG_SIZE)
+ fprintf(stderr, "Warning: file is %d bytes, suspiciously large for a BASIC program.\n", filelen);
fclose(input_file);
- if(got < MIN_PROG_SIZE)
+ if(filelen < MIN_PROG_SIZE)
die("File too short to be a BASIC program (truncated?)\n");
- return got;
+}
+
+int writefile(void) {
+ int outbytes;
+
+ outbytes = fwrite(program, 1, filelen, output_file);
+ fclose(output_file);
+ if(verbose) fprintf(stderr, "Wrote %d bytes.\n", outbytes);
+ return outbytes;
}
/* get a 16-bit value from the file, in 6502 LSB/MSB order. */
@@ -76,6 +102,8 @@ void parse_header(void) {
vvstart = vvtp - TBL_OFFSET;
code_end = starp - TBL_OFFSET;
+ if(lomem) die("This doesn't look like an Atari BASIC program (no $0000 signature).");
+
if(filelen < code_end) {
fprintf(stderr, "Warning: file is truncated: %d bytes, should be %d.\n", filelen, code_end);
}
@@ -111,9 +139,9 @@ void move_code(int offset) {
stmtab += offset;
stmcur += offset;
starp += offset;
+ filelen += offset;
update_header();
parse_header();
- filelen += offset;
}
void adjust_vntable_size(int oldsize, int newsize) {
@@ -127,6 +155,53 @@ void adjust_vntable_size(int oldsize, int newsize) {
}
}
+/* return true if the variable name table is OK */
+int vntable_ok(void) {
+ int vp, bad;
+
+ if(vntp == vntd) {
+ if(verbose) fprintf(stderr, "No variables.\n");
+ return 1;
+ }
+
+ /* first pass: bad = 1 if all the bytes in the table have the same
+ value, no matter what it is. */
+ vp = vnstart + 1;
+ bad = 1;
+ while(vp < vvstart - 1) {
+ if(program[vp] != program[vnstart]) {
+ bad = 0;
+ break;
+ }
+ vp++;
+ }
+ if(bad) return 0;
+
+ /* 2nd pass: bad = 1 if there's any invalid character in the table. */
+ vp = vnstart;
+ while(vp < vvstart) {
+ unsigned char c = program[vp];
+
+ /* treat a null byte as end-of-table, ignore any junk between it and VNTP. */
+ if(c == 0) break;
+
+ vp++;
+
+ /* inverse $ or ( is OK */
+ if(c == 0xa4 || c == 0xa8) continue;
+
+ /* numbers and letters are allowed, inverse or normal. */
+ c &= 0x7f;
+ if(c >= 0x30 && c <= 0x39) continue;
+ if(c >= 0x41 && c <= 0x5a) continue;
+
+ bad++;
+ break;
+ }
+
+ return !bad;
+}
+
void invalid_args(const char *arg) {
fprintf(stderr, "%s: Invalid argument '%s'.\n\n", self, arg);
exit(1);