.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "UNPROTBAS" 1 "2024-05-19" "0.2.1" "Urchlay's Atari 8-bit Tools" .SH NAME unprotbas \- Unprotect LIST-protected Atari 8-bit BASIC programs .SH SYNOPSIS .sp 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 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 (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 output, but \fBunprotbas\fP will refuse to write to standard output if it\(aqs a terminal (since tokenized BASIC is binary data and may confuse the terminal). .SH OPTIONS .sp Option bundling is not supported, use e.g. \fB\-v \-f\fP, not \fB\-vf\fP\&. To use filenames beginning with \fI\-\fP, write them as \fI\&./\-file\fP, or they will be treated as options. .INDENT 0.0 .TP .B \fB\-v\fP 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). 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, it\(aqs left as\-is, in case it\(aqs actually data used by the program. .TP .B \fB\-c\fP Check only. Does a dry run. Loads the program, unprotects it in memory, but doesn\(aqt write the result anywhere. In this mode, there is no \fBoutput\-file\fP\&. .UNINDENT .SH EXIT STATUS .INDENT 0.0 .TP .B 0 \fBinput\-file\fP was protected, unprotection was successful. .TP .B 1 I/O error, or \fBinput\-file\fP isn\(aqt a valid BASIC program. .TP .B 2 \fBinput\-file\fP is already an unprotected BASIC program. .UNINDENT .SH DETAILS .sp In the Atari BASIC world, it\(aqs possible to create a SAVEd (tokenized) program that can be RUN from disk (\fBRUN "D:FILE.BAS"\fP) but if it\(aqs LOADed, it will either crash the BASIC interpreter, or LIST as gibberish. This is known as LIST\-protection. Such programs are generally released to the world in protected form; the author privately keeps an unprotected copy so he can modify it. In later days, collections such as the Holmes Archive contain many LIST\-protected programs, for which the unprotected version was never released. .sp One example of LIST\-protection, taken from \fIMapping the Atari\fP (the \fBSTMCUR\fP entry in the memory map) looks like: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 32000 FOR VARI=PEEK(130)+PEEK(131)*256 TO PEEK(132)+PEEK(133)*256:POKE VARI,155:NEXT VARI 32100 POKE PEEK(138)+PEEK(139)*256+2,0:SAVE "D:filename":NEW .ft P .fi .UNINDENT .UNINDENT .sp To use, add the 2 lines of code to your program, then execute them with \fBGOTO 32000\fP in immediate mode. .sp This illustrates both types of protection, which can be (and usually are) applied to the same program: .INDENT 0.0 .TP .B Variable name table scrambling BASIC has specific rules on what are and aren\(aqt considered legal variable names, which are enforced by the tokenization process, at program entry time. However, it doesn\(aqt use the variable names at runtime, when the tokenized file is interpreted. .sp Replacing the variable names with binary gibberish will render the program LIST\-proof, either replacing every variable name with the same control character, or causing LIST to display a long string of binary garbage for each variable name... but the program will still RUN correctly. Note that the original variable names are \fIgone\fP, and cannot be recovered. .sp Line 32000 in the example above does this job, replacing every variable name with the EOL character (155). .sp \fBunprotbas\fP detects a scrambled variable name table, and builds a new one that\(aqs valid. However, since there are no real variable names in the program, the recovery process just invents new ones, named A through Z, A1 through A9, B1 through B9, etc, etc. It\(aqll require human intelligence to figure out what each variable is for, since the names are meaningless. .sp The \fBoutput\-file\fP may not be the exact size that the \fBinput\-file\fP was. Some types of variable\-name scrambling shrink the variable name table to the minimum size (one byte per name), so the rebuilt table will be larger. Other types of scrambling leave the variable name table at its original size, but \fBunprotbas\fP generates only one\- and two\-character variable names, so the rebuilt table might be smaller. .TP .B Bad next\-line pointer 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 program, using the next\-line pointers, in order to delete any existing line 32768 (the previous immediate mode command). If any line\(aqs pointer is set to zero, that means it points to itself. .sp When BASIC tries to traverse a line of code that points to itself as "next" line, it will get stuck in an infinite loop. This not only prevents LIST, it actually prevents any immediate mode command: after LOADing such a file, \fInothing\fP will work (even pressing RESET won\(aqt get you out of it). The only way to use such a program is to 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 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 line of tokenized code currently being executed. .sp \fBunprotbas\fP fixes this simply by calculating what the pointer should be (based on the tokens in the line) and changing it. No information is lost by doing this. .UNINDENT .sp One more thing \fBunprotbas\fP can do is remove extra data from the end of the file. It\(aqs possible for BASIC files to contain extra data that occurs after the end of the program. Some programs use this as a way to load arbitrary binary data into memory along with the program; for other programs, the extra data is truly garbage (e.g. an EOF character if the file came from a CP/M system, or padding to a block size if a dumb implementation of XMODEM was used to transfer the file). .sp Normally, such "garbage" doesn\(aqt hurt anything. BASIC ignores it. Or it normally does... if you suspect it\(aqs causing a problem, you can remove it with the \fB\-g\fP option. If removing the "garbage" causes the program to fail to run, it wasn\(aqt garbage! \fBunprotbas\fP doesn\(aqt remove extra data by default, to be on the safe side. .SH COPYRIGHT .sp WTFPL. See \fI\%http://www.wtfpl.net/txt/copying/\fP for details. .SH AUTHOR .INDENT 0.0 .IP B. 3 Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\&. .UNINDENT .SH SEE ALSO .sp \fBa8eol\fP(1), \fBa8utf8\fP(1), \fBatr2xfd\fP(1), \fBatrsize\fP(1), \fBaxe\fP(1), \fBblob2c\fP(1), \fBblob2xex\fP(1), \fBcart2xex\fP(1), \fBdasm2atasm\fP(1), \fBf2toxex\fP(1), \fBfenders\fP(1), \fBrom2cart\fP(1), \fBunmac65\fP(1), \fBxexamine\fP(1), \fBxexcat\fP(1), \fBxexsplit\fP(1), \fBxfd2atr\fP(1), \fBxex\fP(5), \fBatascii\fP(7). .sp Any good Atari 8\-bit book: \fIDe Re Atari\fP, \fIThe Atari BASIC Reference Manual\fP, the \fIOS Users\(aq Guide\fP, \fIMapping the Atari\fP, etc. .\" Generated by docutils manpage writer. .