aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2024-05-24 04:10:16 -0400
committerB. Watson <urchlay@slackware.uk>2024-05-24 04:25:31 -0400
commit0044a85e0ab54ebec7e1ba47f4a4a6ac2ad29360 (patch)
tree8743967ed2e7b752394c9396e059d04a8b4a4dd1
parente504bcb1a7f45062c575615c22c09c1c9d3eab70 (diff)
downloadbw-atari8-tools-0044a85e0ab54ebec7e1ba47f4a4a6ac2ad29360.tar.gz
unprotbas: implement protection (-p/-pc/-pv).
-rw-r--r--unprotbas.c120
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);