aboutsummaryrefslogtreecommitdiff
path: root/unprotbas.c
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2024-06-03 18:23:28 -0400
committerB. Watson <urchlay@slackware.uk>2024-06-03 18:23:28 -0400
commitf5f7603a55d4fbe9cda585f3464ace490627a6ed (patch)
tree635d542657d54b8153dbe4f4f07c04a0522ecf12 /unprotbas.c
parentfe7fc036ca0f7769fd9b9b771a92a303a323e8ee (diff)
downloadbw-atari8-tools-f5f7603a55d4fbe9cda585f3464ace490627a6ed.tar.gz
protbas: split off protection functions from unprotbas.
Diffstat (limited to 'unprotbas.c')
-rw-r--r--unprotbas.c283
1 files changed, 30 insertions, 253 deletions
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] <inputfile> <outputfile>\n", self);
- fprintf(stderr, " %s [-v] [-p|-pc|-pv] [-xr|-xNN] [-s] <inputfile> <outputfile>\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();