aboutsummaryrefslogtreecommitdiff
path: root/unprotbas.1
blob: 3b8b832509806231696e77ec8d0ff172cf39ee82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
.\" 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-18" "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 LIST\-protected Atari 8\-bit BASIC programs,
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.
.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
.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.
.TP
.B \fB\-n\fP
Don\(aqt rebuild the variable table (only fix the line pointers, if
needed).
.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.
.UNINDENT
.SH EXIT STATUS
.sp
Exit status is zero for success, non\-zero for failure.
.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 be larger than the \fBinput\-file\fP was, since
some types of variable\-name scrambling shrink the variable name
table to the minimum size (one byte per name); the rebuilt table
will be larger.
.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
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 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).
.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.
.