[Coco] Fwd: Shift-Break-Reset: Recollections from the CoCo 1 days
Arthur Flexser
flexser at fiu.edu
Sun May 3 17:25:56 EDT 2020
Here's a very interesting story from the CoCo 1 days, a bit of curious CoCo
hackery known to very few people. How many folks here (I'll guess: none)
are aware that a 64K CoCo 1 or 2 can be fooled into booting up as a 4K CoCo
by hitting reset while pressing certain combinations of keys? And further,
that this odd fact can provide a means of breaking out of a reset-protected
program and obtaining a snapshot of the program's memory contents,
providing a crucial shortcut for anyone wishing to circumvent the copy
protection?
This bit of reminiscence on my part grew out of a recent interview Tim
Lindner did with Marty Goodman, in which Tim, who had somehow heard of what
I'll call the Shift-Break-Reset technique (after the keys to be held down
while pressing reset) asked Marty about it and recorded Marty's
recollections as an mp3. You can access that mp3 here:
https://drive.google.com/file/d/17ugWA0rHlwC0_mrsnIjn20F7G-urlUzu/view?usp=sharing
Tim then contacted me for further information, since I had collaborated
with Marty on this, and I was able to recall pretty much all the technical
details involved, having spent quite a bit of time on this, those many
years ago. So, I wrote up what I could remember about it, which follows.
Shortly after I acquired my CoCo 1, I had stumbled upon the fact that
pressing reset while mashing a bunch of keys sometimes succeeded in
breaking you out of a protected program that could not be exited by simply
pressing reset. But this put you into a curious mode where practically
every command you could give gave an out-of-memory ?OM ERROR message.
Pressing reset again returned you to the program you'd broken out of.
Since it didn't seem like you could do anything useful with this bit of
strangeness, I pretty much forgot about it until, years later, I received a
message about it from my long-time online friend and future Rainbow
columnist Marty Goodman, who said that his friend Peter, the author of the
graphics program Graphicom for the CoCo, had discovered that CLOADM and
EXEC, without arguments, worked in this odd mode, a mode that Marty or
Peter had independently also stumbled upon by holding down the zero and six
keys and pressing reset. (Shift, break and reset worked equally well, so I
adopted the Shift-Break-Reset term as an evocative shorthand name for the
technique.)
Marty and Peter speculated that perhaps this state of the CoCo was due to
the held-down keys fooling Basic's boot routine into thinking it was
dealing with 4K memory chips and setting the SAM accordingly. (Memory
size is detected in the boot routine by the testing of PIA lines for
certain ones being jumpered. The same PIA lines are also used by the
keyboard, which makes it possible to "fool" the test by holding down
certain keys.)
Having acquired a good deal of experience in ML programming by then, I
found this an intriguing hint and immediately set out to see if you could
use CLOADM and EXEC to recover full control in 64K SAM mode somehow by
executing some sort of ML program loaded in from cassette in 4K mode. This
would then enable you to break out of a protected program and investigate
its innards as a powerful tool for removing its copy protection..(I was one
of those that Marty refers to in the mp3 that enjoyed doing so for the
intellectual challenge. As a software vendor myself, I certainly had no
interest in allowing software pirates to swap unprotected copies. Marty and
I kept the details given below secret for a lot of years to avoid
encouraging software piracy, though Marty did describe the technique years
later in one of his Rainbow columns without getting into specific details.)
Shift-break-reset only works, by the way, with CoCo's that have either
Color Basic 1.1 or 1.2 since these are the only versions that check at
boot-up for both 4K and 64K memory chips. (Version 1.0 didn't check for
64K and 1.3 doesn't check for 4K.)
Anyway, on consulting the SAM specs, I found that accessing address $FFDD
was what was needed to put the SAM in the mode required for 64K chips So,
my first stab at recovering from 4K mode to 64K mode consisted of CLOADMing
and EXECing the following:
ORCC #$50 disable interrupts
LDA $FFDD go to 64K SAM mode
LDA #'A
STA $510 print an A in the middle of the text
screen
LOOP JMP LOOP
This failed miserably, crashing the machine when it got to the LDA $FFDD
instruction. What could be going on?
I tried doing a shift-break-reset in a newly powered-up machine, followed
by reset to return to 64K SAM mode, and then examined the contents of
memory by flipping through memory pages in the text/SG4 display mode.
I had a short utility to do this that I had written (available on the
ADOS-3 disk as PEEP.BIN), permitting me to flip through the 512-byte RAM
pages one at a time with the up- or down- arrow keys, or 8 at a time
($1000) with shifted arrow keys. I saw something very interesting when I
got to examining the pages above $8000. On each RAM page were two 64-byte
strips that stood out clearly from the background, one near the top of the
screen and one in the lower half, each taking up two screen lines of the 32
x 16 display mode. I almost immediately spotted a resemblance between the
content of these 64-byte strips and the typical contents of Basic's base
page at $0-1FF. (The appearance of the 8-byte keyboard rollover table at
$152-159, 8 bytes of $FF, is quite distinctive.) In the 64K mode, the
strips appeared in the same order as they would have in Basic's base page.
So, it was apparent that RAM addresses get completely reconfigured when you
switch between the 4K and 64K SAM modes: the 4K of memory gets fragmented
into a bunch of 64-byte blocks that get reassigned to RAM addresses above
$8000 in the 64K mode. This allowed me to understand something that had
greatly puzzled me earlier: If you broke out of a reset-protected game
program with shift-break-reset, how was it possible to reenter the program
by pressing reset again, with the effect being the same as if you'd simply
pressed reset within the game? Since the cold start in 4K mode rewrites a
lot of addresses on Basic's base page, wouldn't the base page appear all
wrong to the game program and prevent its resumption? Now the answer was
clear: the only messed up addresses as far as the game was concerned were
those above $8000, RAM addresses only usable if the Basic ROMs were
switched out, and not used by a typical copy-protected program for the CoCo
1 and 2.
It was also now clear why my program crashed when it got to the LDA $FFDD
instruction. It couldn't execute the instructions after that point,
because they were now in a completely different RAM region from the one
that the PC register was pointing at! Was recovery possible at all, given
this weird situation? You could JMP to a different address, but there was
no place to put the JMP instruction: If you put it prior to the $FFDD
access, then the LDA $FFDD would be bypassed, and if you put it after, the
JMP would fail to be executed because the PC register was no longer
pointing to its address.
I constructed a table listing each 64-byte strip's location in 4K mode and
its corresponding address in the 64K mode, since the pattern of
reassignment could be inferred from my visual observations. I had the idea
of looking to see if there were any 64-byte strips whose addresses in the
two modes differed by a multiple of $2000.
One thing I had learned in playing around with the 4K mode was that
addresses in this mode were interpreted as modulo $2000. That is, if a JMP
$4520 instruction occurred, it would have the same effect as JMP $0520.
This led me to search my table of corresponding addresses to see if there
were any that were separated by a multiple of $2000, for I had an idea as
to how recovery from 4K mode might be possible if such a correspondence
existed.
I found exactly one pair of addresses with this property: $A80 in 4K mode
became $AA80 when the SAM was switched to 64K mode. Now, suppose, in a
program located at $A80 and running in 4K mode, you put in an instruction
that advanced the program counter by an increment of $A000. This would
have no effect at all while you were in 4K mode, since addresses are
interpreted in modulo $2000, with $A80 being considered the same as $AA80
while you were in that mode. But, once you switched to 64K SAM mode, the
program counter would now be pointing to the correct point to continue
execution with the instruction right after the LDA $FFDD! Tada!! (A
slight caveat: You also need to include LDA $FFDF to put the CoCo into the
all-RAM mode to avoid a jump to the $Axxx area being considered as a ROM
call.)
(Fortunately, $A80 and above is not a critical area for Basic, so loading a
short cassette program to there does not cause Basic to crash.)
So, I set my ORG statement to an appropriate value so that the last byte of
the LDA $FFDD would be the byte before $A80, after inserting the
instructions LDA $FFDF and JMP $A000,PC just before the LDA $FFDD.
I typed EXEC and held my breath as I pressed the Enter key to see if the
"A" would appear in the middle of the screen.
It did!!!!!!!
This meant that 64 bytes of any instructions you wanted could be inserted
after the LDA $FFDD and would be executed in 64K SAM mode! In fact, you
weren't even limited to 64 bytes, because you could put in a jump to the
next 64-byte strip if you needed to run code longer than 64 bytes.
I excitedly communicated all this to Marty a short time later in an online
chat, and he whipped up a couple of utilities shorter than 64 bytes to do
block moves of memory areas that needed to be preserved for purposes of
bypassing copy protection, such as the base page of memory. By this
technique, as Marty put it, we were able to "cut the Gordian knot" and
concoct a version of the protected program that simply reinstated what it
expected to find in memory, thus allowing it to work, without having to
unravel the gory details of its protection scheme. An unexpected bonus of
the way the 4K memory contents redistributed themselves to RAM above $8000
in 64K mode was that not a single byte of the original contents of the 32K
of RAM below $8000 was "messed up" by using the shift-break-reset recovery
method. So, to bypass the protection scheme of a copy-protected program
that ran in 32K of RAM, you could simply reinstate the original memory
contents of those 32K and all that would be left would be to find an
appropriate entry point to execute the program from.
(The game's original RAM contents above $8000, not preserved by the
shift-break-reset technique, were not ordinarily needed, being seldom if
ever used by copy-protected programs for the CoCo 1/2. Though these were
recoverable if they should be needed by a different technique, using a
modified ROM that had code patched into the reset routine that caused a
cold start if a certain key was held down while reset was pressed,
regardless of the status of the warm start flag.)
A short time later, Marty communicated to me that he and Peter had figured
out a way that a software developer could protect against the
shift-break-reset technique if he understood it thoroughly. That would
consist of putting a $55 byte at the address in 64K SAM mode that
corresponded to the warm start flag address ($71) in 4K mode. This would
prevent shift-break reset from causing a cold start in 4K mode, so you
could not break out of the reset-protected program. I actually discovered
such code some time later in a game program from (I think) Spectral
Associates, so we were apparently not the first to hit on the
shift-break-reset technique.
Anyway, that's what I remember about shift-break-reset. Fun reminiscing
about it! I'm a bit surprised I remembered it in such detail!
Art
More information about the Coco
mailing list