diff options
-rw-r--r-- | unprotbas.c | 120 |
1 files changed, 90 insertions, 30 deletions
diff --git a/unprotbas.c b/unprotbas.c index a3ae9cf..8540e6a 100644 --- a/unprotbas.c +++ b/unprotbas.c @@ -61,6 +61,8 @@ int was_protected = 0; int verbose = 0; int readmap = 0; int writemap = 0; +int protect_vars = 0; +int protect_code = 0; /* file handles */ FILE *input_file = NULL; @@ -155,14 +157,23 @@ int fixline(int linepos) { /* +3 here to skip the line number + line length */ int token, done = 0, offset = data[linepos + 3]; + /* this works for lines with multiple statements (colons): */ while(!done) { + fprintf(stderr, "offset was %02x\n", offset); offset = data[linepos + offset]; token = data[linepos + offset - 1]; - /* fprintf(stderr, "offset %02x token %02x\n", offset, token); */ + fprintf(stderr, "offset %02x token %02x\n", offset, token); if(token != 0x14) done++; } + /* otherwise, the first statement being the only statement, use its + next-statement offset. */ + if(!offset) { + offset = data[linepos + 3]; + fprintf(stderr, "offset now %02x\n", offset); + } + data[linepos + 2] = offset; return offset; } @@ -207,6 +218,30 @@ int fixcode(void) { return result; } +/* iterate over all the lines, zero out the offset of the last one + 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 = data[pos + 2]; + if(!offset) + die("program already was code-protected"); + oldpos = pos; + pos += offset; + } + } + + data[oldpos + 2] = 0; + fprintf(stderr, "set invalid line pointer at line %d\n", lineno); +} + /* sometimes the variable name table isn't large enough to hold the generated variable names. move_code() makes more space, by moving the rest of the program (including the variable value @@ -539,6 +574,13 @@ void apply_var_map(void) { memmove(data + vnstart, new_vntable, newp); } +void scramble_vars(void) { + int i; + + for(i = vnstart; i < vvstart - 1; i++) + data[i] = '\x9b'; +} + void print_help(void) { fprintf(stderr, "Usage: %s [-v] [-f] [-n] [-g] [-c] [-r|-w] <inputfile> <outputfile>\n", self); fprintf(stderr, "-v: verbose\n"); @@ -613,6 +655,19 @@ 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 0: if(!input_file) open_input(NULL); @@ -648,41 +703,46 @@ int main(int argc, char **argv) { if(lomem) die("This doesn't look like an Atari BASIC program (no $0000 signature)"); - if(readmap) { - was_protected = !vntable_ok(); - read_var_map(); - apply_var_map(); + if(protect_code || protect_vars) { + if(protect_vars) scramble_vars(); + if(protect_code) breakcode(); } 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(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(fixcode()) { - if(verbose) fprintf(stderr, "Fixed invalid offset in code\n"); - was_protected = 1; - } else { - if(verbose) fprintf(stderr, "No invalid offsets\n"); - } + if(fixcode()) { + if(verbose) fprintf(stderr, "Fixed invalid offset in code\n"); + was_protected = 1; + } else { + if(verbose) fprintf(stderr, "No invalid offsets\n"); + } - if(verbose) { - if(was_protected) - fprintf(stderr, "Program was protected.\n"); - else - fprintf(stderr, "Program was NOT protected.\n"); - } + if(verbose) { + if(was_protected) + fprintf(stderr, "Program was protected.\n"); + else + fprintf(stderr, "Program was NOT protected.\n"); + } - if(checkonly) { - if(verbose) fprintf(stderr, "Check-only mode; no output written.\n"); - if(was_protected) - return 0; - else - return 2; + if(checkonly) { + if(verbose) fprintf(stderr, "Check-only mode; no output written.\n"); + if(was_protected) + return 0; + else + return 2; + } } int got = fwrite(data, 1, filelen, output_file); |