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