From a076240e441bf4b7e7f4f29cbfbb9fb2d3336c09 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Sun, 19 May 2024 14:26:16 -0400 Subject: unprotbas: implement -v option, fix doc about line 32768. --- unprotbas.1 | 23 +++++++++-------------- unprotbas.c | 36 +++++++++++++++++++----------------- unprotbas.rst | 23 +++++++++-------------- 3 files changed, 37 insertions(+), 45 deletions(-) diff --git a/unprotbas.1 b/unprotbas.1 index f770079..ff8cd36 100644 --- a/unprotbas.1 +++ b/unprotbas.1 @@ -35,12 +35,12 @@ unprotbas \- Unprotect LIST-protected Atari 8-bit BASIC programs unprotbas [\fB\-v\fP] [\fB\-f\fP] [\fB\-n\fP] [\fB\-g\fP] \fBinput\-file\fP \fBoutput\-file\fP .SH DESCRIPTION .sp -\fBunprotbas\fP modifies LIST\-protected Atari 8\-bit BASIC programs, +\fBunprotbas\fP modifies a LIST\-protected Atari 8\-bit BASIC program, creating a new non\-protected copy. See \fBDETAILS\fP, below, to understand how the protection and unprotection works. .sp -\fBinput\-file\fP must be a tokenized Atari BASIC program. Use \fI\-\fP to -read from standard input. +\fBinput\-file\fP must be a tokenized (SAVEd) Atari BASIC program. Use +\fI\-\fP to read from standard input. .sp \fBoutput\-file\fP will be the unprotected tokenized BASIC program. If it already exists, it will be overwritten. Use \fI\-\fP to write to standard @@ -55,14 +55,15 @@ will be treated as options. .INDENT 0.0 .TP .B \fB\-v\fP -Verbose operation. TODO: it\(aqs always verbose right now... +Verbose operation. .TP .B \fB\-f\fP Force the variable name table to be rebuilt, even if it looks OK. +This option cannot be combined with \fB\-n\fP\&. .TP .B \fB\-n\fP Don\(aqt rebuild the variable table (only fix the line pointers, if -needed). +needed). This option cannot be combined with \fB\-f\fP\&. .TP .B \fB\-g\fP Remove any "garbage" data from the end of the file. By default, @@ -150,11 +151,6 @@ generates only one\- and two\-character variable names, so the rebuilt table might be smaller. .TP .B Bad next\-line pointer -Generally, this is done with line number 32768. Yes, this line -number is outside the range BASIC accepts... but BASIC uses it -internally for immediate\-mode commands. And when SAVE or CSAVE are -executed, this line gets saved, too. -.sp Every line of tokenized BASIC contains a line length byte, which BASIC uses as a pointer to the next line of code. Before printing the READY prompt, BASIC iterates over every line of code in the @@ -171,10 +167,9 @@ use the RUN command with a filename, and if the program ever exits (due to END, STOP, an error, or the Break key), BASIC will get stuck again. .sp -This doesn\(aqt \fIhave\fP to be done with line 32768. Any line of code -that doesn\(aqt have to be traversed at runtime would work (in other -words, a regular line whose line number is higher than any code that -ever gets executed, usually the last line in the file). +This doesn\(aqt \fIhave\fP to be done with the last line in the +program. The "poisoned" line could be followed by more lines of +code, though they could never actually execute. .sp Line 32100 in the example above does this job, taking advantage of the STMCUR pointer used by BASIC, which holds the address of the diff --git a/unprotbas.c b/unprotbas.c index 02263ca..0b11e0e 100644 --- a/unprotbas.c +++ b/unprotbas.c @@ -58,7 +58,7 @@ void die(const char *msg) { /* read entire file into memory */ int readfile(void) { int got = fread(data, 1, 65535, input_file); - fprintf(stderr, "read %d bytes\n", got); + if(verbose) fprintf(stderr, "read %d bytes\n", got); fclose(input_file); return got; } @@ -90,7 +90,7 @@ void read_header(void) { codestart = stmtab - STM_OFFSET - (vntp - 256); vnstart = vntp - 256 + 14; vvstart = vvtp - 256 + 14; - dump_header_vars(); + if(verbose) dump_header_vars(); } void set_header_vars(void) { @@ -167,7 +167,7 @@ int fixcode(void) { offset = data[pos + 2]; /* fprintf(stderr, "pos %d, line #%d, offset %d\n", pos, lineno, offset); */ if(offset < 6) { - fprintf(stderr, "Found invalid offset %d (<6) at line %d\n", offset, lineno); + if(verbose) fprintf(stderr, "Found invalid offset %d (<6) at line %d\n", offset, lineno); offset += fixline(pos); result++; } @@ -178,10 +178,10 @@ int fixcode(void) { if(lineno == 32768) break; } - fprintf(stderr, "End program pos $%04x/%d\n", pos, pos); + if(verbose) fprintf(stderr, "End program pos $%04x/%d\n", pos, pos); if(filelen > pos) { - fprintf(stderr, "trailing garbage at EOF, %d bytes, %s\n", + if(verbose) fprintf(stderr, "trailing garbage at EOF, %d bytes, %s\n", filelen - pos, (keepgarbage ? "keeping" : "removing")); if(!keepgarbage) filelen = pos; } @@ -233,7 +233,7 @@ int vntable_ok(void) { int vp, bad; if(vntp == vntd) { - fprintf(stderr, "No variables\n"); + if(verbose) fprintf(stderr, "No variables\n"); return 1; } @@ -345,7 +345,7 @@ void adjust_vntable_size(int oldsize, int newsize) { int move_by; if(oldsize != newsize) { move_by = newsize - oldsize; - fprintf(stderr, "need %d bytes for vntable, have %d, moving VVTP by %d to %04x\n", + if(verbose) fprintf(stderr, "need %d bytes for vntable, have %d, moving VVTP by %d to %04x\n", newsize, oldsize, move_by, vvtp + move_by); move_code(move_by); } @@ -473,26 +473,28 @@ int main(int argc, char **argv) { if(!keepvars) { if(fixvars()) { was_protected = 1; - fprintf(stderr, "Variable names replaced\n"); + if(verbose) fprintf(stderr, "Variable names replaced\n"); } else { - fprintf(stderr, "Variable names were already OK\n"); + if(verbose) fprintf(stderr, "Variable names were already OK\n"); } } if(fixcode()) { - fprintf(stderr, "Fixed invalid offset in code\n"); + if(verbose) fprintf(stderr, "Fixed invalid offset in code\n"); was_protected = 1; } else { - fprintf(stderr, "No invalid offsets\n"); + if(verbose) fprintf(stderr, "No invalid offsets\n"); } - 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) { - fprintf(stderr, "Check-only mode; no output written.\n"); + if(verbose) fprintf(stderr, "Check-only mode; no output written.\n"); if(was_protected) return 0; else @@ -501,7 +503,7 @@ int main(int argc, char **argv) { int got = fwrite(data, 1, filelen, output_file); fclose(output_file); - fprintf(stderr, "wrote %d bytes\n", got); + if(verbose) fprintf(stderr, "wrote %d bytes\n", got); return 0; } diff --git a/unprotbas.rst b/unprotbas.rst index daf391f..dfd3f5a 100644 --- a/unprotbas.rst +++ b/unprotbas.rst @@ -16,12 +16,12 @@ unprotbas [**-v**] [**-f**] [**-n**] [**-g**] **input-file** **output-file** DESCRIPTION =========== -**unprotbas** modifies LIST-protected Atari 8-bit BASIC programs, +**unprotbas** modifies a LIST-protected Atari 8-bit BASIC program, creating a new non-protected copy. See **DETAILS**, below, to understand how the protection and unprotection works. -**input-file** must be a tokenized Atari BASIC program. Use *-* to -read from standard input. +**input-file** must be a tokenized (SAVEd) Atari BASIC program. Use +*-* to read from standard input. **output-file** will be the unprotected tokenized BASIC program. If it already exists, it will be overwritten. Use *-* to write to standard @@ -37,14 +37,15 @@ To use filenames beginning with *-*, write them as *./-file*, or they will be treated as options. **-v** - Verbose operation. TODO: it's always verbose right now... + Verbose operation. **-f** Force the variable name table to be rebuilt, even if it looks OK. + This option cannot be combined with **-n**. **-n** Don't rebuild the variable table (only fix the line pointers, if - needed). + needed). This option cannot be combined with **-f**. **-g** Remove any "garbage" data from the end of the file. By default, @@ -124,11 +125,6 @@ Variable name table scrambling table might be smaller. Bad next-line pointer - Generally, this is done with line number 32768. Yes, this line - number is outside the range BASIC accepts... but BASIC uses it - internally for immediate-mode commands. And when SAVE or CSAVE are - executed, this line gets saved, too. - Every line of tokenized BASIC contains a line length byte, which BASIC uses as a pointer to the next line of code. Before printing the READY prompt, BASIC iterates over every line of code in the @@ -145,10 +141,9 @@ Bad next-line pointer (due to END, STOP, an error, or the Break key), BASIC will get stuck again. - This doesn't *have* to be done with line 32768. Any line of code - that doesn't have to be traversed at runtime would work (in other - words, a regular line whose line number is higher than any code that - ever gets executed, usually the last line in the file). + This doesn't *have* to be done with the last line in the + program. The "poisoned" line could be followed by more lines of + code, though they could never actually execute. Line 32100 in the example above does this job, taking advantage of the STMCUR pointer used by BASIC, which holds the address of the -- cgit v1.2.3