From f5f7603a55d4fbe9cda585f3464ace490627a6ed Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Mon, 3 Jun 2024 18:23:28 -0400 Subject: protbas: split off protection functions from unprotbas. --- unprotbas.c | 283 +++++++----------------------------------------------------- 1 file changed, 30 insertions(+), 253 deletions(-) (limited to 'unprotbas.c') diff --git a/unprotbas.c b/unprotbas.c index 8c5c14a..5bde236 100644 --- a/unprotbas.c +++ b/unprotbas.c @@ -18,21 +18,6 @@ or whatever), we "fix" that by making up new variable names. */ -/* for the -p/-pc options: 32767 END */ -unsigned char badcode[] = { - 0xff, 0x7f, /* line number 32767 */ - 0x00, /* *bad* next-line offset */ - 0x06, /* next-statement offset */ - 0x15, /* END token */ - 0x16, /* end-of-line token */ -}; - -/* for -p/-pv */ -int varname_char = 0x9b; - -/* for -s */ -int shrinktable = 0; - /* for the -r option */ #define MAP_FILE "varnames.txt" unsigned char varnames[BUFSIZE]; @@ -47,10 +32,6 @@ int checkonly = 0; int was_protected = 0; int readmap = 0; int writemap = 0; -int protect_vars = 0; -int protect_code = 0; - -char *output_filename = NULL; /* fixline() calculates & sets correct line length, by iterating over the statement(s) within the line. the last statement's @@ -149,50 +130,6 @@ int fixcode(void) { return result; } -/* iterate over all the lines, insert a poisoned line 32767 just - before line 32768 */ -void breakcode(void) { - int pos = codestart, oldpos = 0; - int offset, lineno = -1, tmpno = -1; - - while(pos < filelen) { - lineno = tmpno; - tmpno = getword(pos); - if(tmpno == 32768) { - break; - } else { - offset = program[pos + 2]; - if(!offset) { - fprintf(stderr, "%s: program already was code-protected.\n", self); - exit(2); - } - oldpos = pos; - pos += offset; - } - } - - if(!oldpos) die("Can't protect code because there are no lines of code."); - if(lineno == 32767) die("Can't protect code because there is already a line 32767."); - - /* pos is now the start of line 32768, move it up to make room for - the new line */ - offset = sizeof(badcode); - memmove(program + pos + offset, program + pos, filelen); - - /* insert new line */ - memmove(program + pos, badcode, offset); - - if(verbose) - fprintf(stderr, "Inserted line 32767 with invalid offset at file offset $%04x.\n", pos); - - /* update pointers that would be affected by the code move */ - stmcur += offset; - starp += offset; - update_header(); - parse_header(); - filelen += offset; -} - /* Fixing the variables is a bit more work than it seems like it might be, because the last byte of the name has to match the type (inverse video "(" for numeric array, inverse "$" for @@ -217,53 +154,6 @@ void breakcode(void) { or letter+number or one-letter string/array names). */ -/* 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; -} - /* walk the variable value table, generating variable names. if write is 0, just return the size the table will be. if write is 1, actually write the names to memory. */ @@ -495,44 +385,8 @@ void apply_var_map(void) { memmove(program + vnstart, new_vntable, newp); } -void scramble_vars(void) { - int i; - - if(!vntable_ok()) { - fprintf(stderr, "%s: Program already was variable-protected.\n", self); - exit(2); - } - - if(shrinktable) { - if(verbose) fprintf(stderr, "Shrinking variable name table.\n"); - adjust_vntable_size((vvstart - 1) - vnstart, (codestart - vvstart) / 8); - } - - if(varname_char == -1) srand(time(NULL)); - - for(i = vnstart; i < vvstart - 1; i++) - if(varname_char == -1) - program[i] = (rand() >> 8) & 0xff; - else - program[i] = varname_char & 0xff; - - if(verbose) { - i -= vnstart; - if(i) { - fprintf(stderr, "Replaced %d byte variable name table with ", i); - if(varname_char == -1) - fprintf(stderr, "random characters.\n"); - else - fprintf(stderr, "character $%02x.\n", varname_char); - } else { - die("Can't protect variables because there are no variables."); - } - } -} - void print_help(void) { fprintf(stderr, "Usage: %s [-v] [-f] [-n] [-g] [-c] [-r|-w] \n", self); - fprintf(stderr, " %s [-v] [-p|-pc|-pv] [-xr|-xNN] [-s] \n", self); fprintf(stderr, " -v: Verbose.\n"); fprintf(stderr, " -f: Force variable name table rebuild.\n"); fprintf(stderr, " -n: Do not rebuild variable name table, even if it's invalid.\n"); @@ -540,32 +394,13 @@ void print_help(void) { fprintf(stderr, " -c: Check only; no output file.\n"); fprintf(stderr, " -w: Write variable names to 'varnames.txt'.\n"); fprintf(stderr, " -r: Read variable names from 'varnames.txt'.\n"); - fprintf(stderr, " -pc/-pv/-p: Protect code/variables/both.\n"); - fprintf(stderr, " -s: Shrink variable name table to min size, with -p/-pv.\n"); - fprintf(stderr, " -xNN: Hex code NN for variable names, with -p/-pv.\n"); - fprintf(stderr, " -xr: Random variable names, with -p/-pv.\n"); fprintf(stderr, "Use - as a filename to read from stdin and/or write to stdout.\n"); } void parse_args(int argc, char **argv) { - int xopt_used = 0; - set_self(*argv); - if(argc < 2) { - print_help(); - exit(1); - } - - if(strcmp(argv[1], "--help") == 0) { - print_help(); - exit(0); - } - - if(strcmp(argv[1], "--version") == 0) { - printf("%s %s\n", self, VERSION); - exit(0); - } + parse_general_args(argc, argv, print_help); while(++argv, --argc) { if((*argv)[0] == '-') { @@ -577,37 +412,6 @@ void parse_args(int argc, char **argv) { case 'c': checkonly = 1; break; case 'r': readmap = 1; break; case 'w': writemap = 1; break; - case 'p': { - switch((*argv)[2]) { - case 'c': - protect_code = 1; break; - case 'v': - protect_vars = 1; break; - case 0: - protect_code = protect_vars = 1; break; - default: - die("Invalid -p suboption (only -p, -pc, -pv are valid)."); - } - } - break; - case 'x': { - xopt_used++; - switch((*argv)[2]) { - case 'r': - varname_char = -1; break; - case 0: - die("-x option requires a hex number or 'r' (e.g. -x20, not -x 20)."); break; - default: - { - char *e; - varname_char = (int)strtol(&(*argv)[2], &e, 16); - if(*e != 0 || varname_char > 0xff) - die("invalid hex value for -x option (range is 0 to ff)."); - } - } - } - break; - case 's': shrinktable = 1; break; case 0: if(!input_file) open_input(NULL); @@ -635,80 +439,53 @@ void parse_args(int argc, char **argv) { if(readmap && writemap) die("-r and -w are mutually exclusive."); if(readmap && keepvars) die("-r and -n are mutually exclusive, maybe you want -w?"); if(checkonly && (readmap || writemap)) die("-c and -r/-w are mutually exclusive."); - if(protect_code || protect_vars) { - if(checkonly || keepvars || forcevars || readmap || writemap || !keepgarbage) - die("-p, -pc, -pv options can only be combined with -v, -x, -s."); - } - if(xopt_used && !protect_vars) - die("-x option requires -p or -pv."); - if(shrinktable && !protect_vars) - die("-s option requires -p or -pv."); } int main(int argc, char **argv) { - int outbytes, invoffs = 0; + int invoffs = 0; parse_args(argc, argv); - filelen = readfile(); + readfile(); parse_header(); - if(lomem) die("This doesn't look like an Atari BASIC program (no $0000 signature)."); - - if(protect_code || protect_vars) { - if(verbose) { - fprintf(stderr, "Protecting program, "); - if(protect_vars && !protect_code) - fprintf(stderr, "variables only.\n"); - else if(protect_code && !protect_vars) - fprintf(stderr, "code only.\n"); - else - fprintf(stderr, "both code and variables.\n"); - } - if(protect_vars) scramble_vars(); - if(protect_code) breakcode(); - was_protected = 1; /* opposite sense for this one */ + if(readmap) { + was_protected = !vntable_ok(); + read_var_map(); + apply_var_map(); } else { - if(readmap) { - was_protected = !vntable_ok(); - read_var_map(); - apply_var_map(); - } else { - if(!keepvars) { - if(fixvars()) { - was_protected = 1; - if(verbose) fprintf(stderr, "Variable names replaced.\n"); - } else { - if(verbose) fprintf(stderr, "Variable names were already OK.\n"); - } + if(!keepvars) { + if(fixvars()) { + was_protected = 1; + if(verbose) fprintf(stderr, "Variable names replaced.\n"); + } else { + if(verbose) fprintf(stderr, "Variable names were already OK.\n"); } } + } - invoffs = fixcode(); - if(invoffs) { - if(verbose) - fprintf(stderr, "Fixed %d invalid offset%s in code.\n", - invoffs, (invoffs == 1 ? "" : "s")); - was_protected = 1; - } else { - if(verbose) fprintf(stderr, "No invalid offsets.\n"); - } + invoffs = fixcode(); + if(invoffs) { + if(verbose) + fprintf(stderr, "Fixed %d invalid offset%s in code.\n", + invoffs, (invoffs == 1 ? "" : "s")); + was_protected = 1; + } else { + if(verbose) fprintf(stderr, "No invalid offsets.\n"); + } - if(verbose) { - fprintf(stderr, "Program was %sprotected.\n", (was_protected ? "" : "NOT ")); - } + if(verbose) { + fprintf(stderr, "Program was %sprotected.\n", (was_protected ? "" : "NOT ")); + } - if(checkonly) { - if(verbose) fprintf(stderr, "Check-only mode; no output written.\n"); - return was_protected ? 0 : 2; - } + if(checkonly) { + if(verbose) fprintf(stderr, "Check-only mode; no output written.\n"); + return was_protected ? 0 : 2; } /* we don't open the output file until all processing is done, to avoid leaving invalid output files if we exit on error. */ open_output(output_filename); - outbytes = fwrite(program, 1, filelen, output_file); - fclose(output_file); - if(verbose) fprintf(stderr, "Wrote %d bytes.\n", outbytes); + writefile(); if(writemap) write_var_map(); -- cgit v1.2.3