[comp.sys.atari.8bit] Cartridge Update - Centipede, Battlezone

cfchiesa@bsu-cs.UUCP (Christopher Chiesa) (06/06/88)

In a recent series of articles here, I discussed my explorations of Atari's 
CENTIPEDE game cartridge, vis-a-vis making a disk-based copy for self-educa-
tional purposes.  At that time, I had been able to copy the 8K of data from
cartridge ROM to disk, load the same data back into RAM at the original ad-
dresses, and get a "partial" execution of the "intro" portion of the program.
Attempts to continue on into the "game" portion of the program resulted in
system freeze-up.

I asked for suggestions as to why this might be happening, i.e. what techniques
Atari might have used to discourage RAM execution while allowing ROM execu-
tion.  Thanks to all who responded, especially Hans Breitenlohner 
(hans@umd5.umd.edu), Ray Wilmott (wilmott@topaz.rutgers.edu), and Andy A. Lee
(alif+@andrew.cmu.edu).  After printing, saving, and absorbing (!) your com-
ments, I'm pleased to announce that I was finally SUCCESSFUL in getting that
disk version running.

In the interest of helping others as I have been helped, here then is a brief
summary of what I found in CENTIPEDE.  Following THAT, I will also comment on
the results of similar investigations into the new BATTLEZONE cartridge.

CENTIPEDE:
---------

   Centipede turns out to be an 8K cartridge, performs NO esoteric bank-
switching or relocating, etc.  Execution occurs within the standard left-
cartridge (400/800; the ONLY cartridge, XL/XE series) address range of 
$A000 - $BFFF.  One of the first things the program does is to establish 
its own Vertical Blank Interrupt service routines, which appear to be con-
cerned in part with shadowing console key readings ($D01F-- CONSOL) into
RAM.  This incidentally locks OUT such standard functions as keyboard-
reading and the like, making single-step debugging more or less impossible 
(analysis proceeded by looking at static disassembly output).

   Protection is implemented at two separate points in the code.  The first
comes at address $A087, where LSRs are performed on data within the cartridge
space itself.  The address being LSR'd turns out to be the entry point for the
main game-playing routine; if the program is executing from an inserted cart-
ridge, the LSRs have no effect on the data/code being LSR'd -- but if it's 
executing from a RAM copy, this effectively "trashes" the code at that address.
The second line of defense (so to speak) appears around $A151, where once again
an LSR is performed on cartridge-space memory.  This time, the data BEFORE the
LSR is compared with that AFTER the LSR, determining quite neatly whether the
environment is RAM or ROM; if ROM, a JSR is performed to what seems to be the
main game routine; if RAM, a JMP is performed to the SAME address.  The JMP,
of course, fails to stack a return address, and when execution hits an RTS,
there's noplace to return to -- I imagine execution ATTEMPTS to continue with
whatever follows the "jump to loaded application" portion of the operating
system!


BATTLEZONE:
----------

   After the success with Centipede, a friend and I decided to take a look at
the new BATTLEZONE cartridge.  First off, for those who've been wondering, I
can personally guarantee that it DOES run on BOTH the 800XL and the original
800 -- no matter what the sellers of the XEGS may tell you!  This in itself is
significant, for reasons I'll get to momentarily.

   Battlezone banks into memory looking like a 16K cartridge: addresses 
$8000 through $BFFF decode into cartridge ROM.   Execution begins at $B000,
and IMMEDIATELY things get complicated.  

   Hans Breitenlohner explained to me a little about the role of location $D500
in implementing more-than-16K cartridges; basically, what seems to happen is
that storing a value into $D500 affects what appears at addresses $8000-$9FFF
(the RIGHT cartridge space, 400/800).  Specifically, it acts like a "bank 
select" register.  Storing $00 at $D500 results in ONE set of data in $8000-
$9FFF; storing $01 at $D500 results in a totally separate set of data at 
those addresses.  (Note: I am ASSUMING, at present, that $D500 controls the
whole ball o' wax, toggling 8K blocks in and out all at once.  Hans, you men-
tioned that addresses $D500-$D5FF are actually involved in this - that would
imply that the banking segment size was much SMALLER; can you confirm or
refute?  Anyone else?)  Initialization of BATTLEZONE consists of storing #$00
at $D500, copying 8K of data from the bank at $8000-9FFF, to RAM at $4000-$5FFF,
then storing #$01 at $D500 and copying a second 8K to $6000-$7FFF, then stor-
ing #$02 at $D500 and performing a JMP $4000 .  Whew.  That cartridge copies
16K of itself into RAM, and sets up a THIRD 8K for access in ROM, JUST in the
INITIALIZATION routine!  Skimming the code, I find that $D500 is manipulated
"on the fly" during execution of the program, banking in I know not how many
more 8K chunks at various times.

   The thing that I find interesting about this, is that it works just as well
on my original-series 800, as on my friend's 800XL.  This makes the $D500 bank-
switching scheme something of an "undocumented" feature all the way from the
beginning of Atari computers!  MAPPING THE ATARI says absolutely NOTHING about
location $D500 (in fact, nothing about any address between $D40F and $D800) in
the "main body," nor in Appendix 11 ("Addenda and Errata to the First Edition"),
of the "Revised Edition."  The only mention of this little marvel is made in
Appendix 12, which states, in part, that it is  "... unused in both XL and
400/800 models"!  The implication, which I think I've just disproved, is that 
didn't even EXIST until the XE series!  And there's NO hint of the bank-swit-
ching capability.

  (Oddly enough, I had a hint of this while trying to track down the iner-
mittent heat failure about which I posted last week -- I noticed in the sche-
matic for the 800 "personality board," that a "$D5xx" line comes out of the 
address multiplexer chip.  Sounds like that might have something to do with
all this, eh?  There was ALSO a "D6xx" line!  What might THAT one do?  Any
takers??)

  Hope this is of interest to someone; note that my investigations are for the
purpose only of understanding my machine, and educating myself and friends in
that direction.  

  Chris Chiesa
  graduate of  Ball State University,  Muncie, IN

 

the effect of  
this is a "delayed effect" defense, since everything goes as intended until
the CPU hits an RTS instruction: if the JSR was performed, control returns
to the instruction following the JSR, and Centipede proceeds unhindered.  If
the JMP was pwe  
 
space, using RAM of course fo 
-- 
UUCP: <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!cfchiesa 
cfchiesa@bsu-cs.UUCP