[comp.sys.atari.8bit] 16K cartridge - How?

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

I've recently been trying to learn about the innards of one of my game cart-
ridges (CENTIPEDE, to be specific).  I find that I can go into BUG/65, move the
display list and display data "out of the way" of the Cartridge memory areas,
then snap the cartridge into the slot and have its ROM suddenly appear in the
appropriate address space. 

Using this arrangement, and assuming for convenience that I plug CENTIPEDE into
the LEFT cartridge slot on my 800, I find that 8K of address space switches from
RAM to Cartridge ROM.  I can then copy this 8K of data down into RAM, unplug 
CENTIPEDE, and copy the data back to its original addresses which are now RAM
again.  The same bytes are now in the same addresses as when CENTIPEDE was there
"in person."  So far, so good.

If I execute at the "cartridge run address," with CENTIPEDE plugged in, it 
works.  I can play CENTIPEDE.  But when I go through the above procedure, and
try executing the SAME code in RAM, it DOESN'T work!  I get a display of the  
title screen, and the "demo mode" makes a fair attempt at execution, but the 
P/M graphics are totally garbled, and you can't get beyond the title screen to
try playing the game.
 
I have several theories about this phenomenon, which I'd like to bounce off
you of the Net.

1) Centipede is a 16K cartridge and I'm just not getting all the code.

    Support: opening the cartridge, there are TWO chips inside, as opposed to
    ONE chip inside Atari BASIC; Atari BASIC DOES work properly under the ROM-
    to-RAM copy scheme described above.

    Questions:

       How do I get at the other 8K ?  Is there a "switch" address in the ROM
       that toggles in the second half "upon request"?  Or does it appear in
       some other, hidden memory block that I haven't found yet?

2) Centipede is an 8K cartridge but detects RAM-vs-ROM execution and bungs up
   if you've moved it to RAM.

    No real proof OR disproof of this one, except that "that's something I'd
    probably do if I were Atari." 


There ARE a few places in the code where an LSR (logical shift right) is per-
formed on memory addresses WITHIN the Cartridge ROM.  I haven't been able to 
determine whether these operations are part of "detecting ROM vs RAM" or "swap-
ping in a second 8K".  I also haven't looked at the WHOLE 8K yet, of course;
it's an ongoing effort and your responses here will be helpful in "pruning" 
paths of inquiry that are in the wrong direction.

Please post or e-mail anything you may know on this type of thing; the manuals
are amazingly sparse.  The only comment I've ever even SEEN about 16K cart-
ridges was something to the effect that "...Atari designed a second slot into
the 800 with the intent of marketing larger-than-8K programs as TWO cartridges,
but then they discovered a way of putting 16K programs into ONE cartridge, ..."

This implies that I'm on the right track, but this is ALL the documentation 
there seems to be.  Thanks in advance for any info you Netpeople can provide!

Chris Chiesa  
-- 
UUCP: <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!cfchiesa 
cfchiesa@bsu-cs.UUCP                                           

hans@umd5.umd.edu (Hans Breitenlohner) (05/06/88)

In article <2806@bsu-cs.UUCP> cfchiesa@bsu-cs.UUCP (Christopher Chiesa) writes:
>
>> about his experiments with ROM vs. RAM versions of cartridge code
>I have several theories about this phenomenon, which I'd like to bounce off
>you of the Net.
>
>1) Centipede is a 16K cartridge and I'm just not getting all the code.

My Centipede cartridge (CXL4020) is definitely an 8k cartridge.

>
>
>    Questions:
>
>       How do I get at the other 8K ?  Is there a "switch" address in the ROM
>       that toggles in the second half "upon request"?  Or does it appear in
>       some other, hidden memory block that I haven't found yet?
>
Standard 16k cartridges occupy memory from $8000 to $BFFF.  There are two
ROM enable lines on the cartridge connector, one for the block $8000-$9FFF
and one for the block $A000-$BFFF.  There are also separate select lines
for the two banks of ROM, and only enough address lines for 8k.  All this
surely is a remnant from the design of the 800's memory.
See "Mapping the Atari", Appendix 14, or the schematics for your system,
for more detail.
Then there are the bank-switched cartridges.  Basic-XE, for instance, crams
16k into an 8k address space.  Switching is done by addressing locations
$D500-$D5FF.  $Bxx addresses one block of ROM or RAM, $Axx addresses one of
three blocks of ROM or RAM.  (I hope I got this right, haven't actually
had a chance to play with one).
Your cartridge definitely is not bank-switched.

>2) Centipede is an 8K cartridge but detects RAM-vs-ROM execution and bungs up
>   if you've moved it to RAM.
>
>    No real proof OR disproof of this one, except that "that's something I'd
>    probably do if I were Atari." 

I would be surprised if this was the case.  

>
>
>There ARE a few places in the code where an LSR (logical shift right) is per-
>formed on memory addresses WITHIN the Cartridge ROM.  I haven't been able to 
>determine whether these operations are part of "detecting ROM vs RAM" or "swap-
>ping in a second 8K".  I also haven't looked at the WHOLE 8K yet, of course;
>it's an ongoing effort and your responses here will be helpful in "pruning" 
>paths of inquiry that are in the wrong direction.
>

I would guess these are data areas or tables of addresses.

>Chris Chiesa  
>-- 


There are other, more innocent possibilities:

1. During initialization the OS sets up numerous pointers based on the size
of RAM that it finds.  Addresses $6A, $2E4-$2E6 come to mind, but there
may be more.  To keep everything away from the cartridge code you have to set
up all of these just right, or someone might trash part or your RAM.  The only
way to be sure you are doing it right is to paw through the OS listings,
and try to duplicate whatever is done there.

2. Some OS scrolling and screen clearing routines touch memory beyond 
the end of the screen area.  Read what "Mapping the Atari" has to say
about location $6A for more details.  There might be some interaction
with BUG/65 and its screen handling, too.  You might experiment with
setting $6A (and related cells) to a value lower than $A0.  Also the
Centipede cartridge might have routines which are doing similar sloppy
things.

3. I would also be concerned about what happens to your system (and memory
contents) when you plug and unplug a cartridge while the system is running.
After all, you are disturbing everybody's address and data bus when you
do that.

Happy hunting,

Hans

wilmott@topaz.rutgers.edu (Ray Wilmott) (05/06/88)

Well, I can't say anything for certain since I don't know for *sure*
why Centipede isn't working when you move it to RAM, but I can say
for *sure* that a lot of cartridges were copy-protected to prevent
people from just dumping their code to disk and having copies being
distributed. A few years back when I was more into hacking on the
Atari, I decided to do just what you're doing - trying to get carts
put onto disk files. Some worked fine. Others didn't work at all, or
worked for a short time (ie - title screen or whatever) and then got
garbled. So I started disassembling the code. Lo and behold, some of
the carts had an interesting protection scheme - namely, they write
garbage bytes to random (or specific) addresses of the carts
residence ($A000-$C000?). If the cart is plugged in, there'll be
ROM there, so writing can do no harm there. If the program happens
to have been converted to RAM, well then it just gets trashed.
Of the 15 or so carts I eventually transferred to disk, about 7 or
8 had this type of protection. Of those, only 1 had the actual
"pokes" hidden in such a way that it didn't immediately jump out at
you when you disassembled the code. The solution is easy enough: just
disassemble the code and replace any code that writes to cart 
locations with a NOP (decimal value 234 I think). Good luck.


				-Ray


wilmott@topaz.rutgers.edu

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

In article <2676@umd5.umd.edu>, hans@umd5.umd.edu (Hans Breitenlohner) writes:
> In article <2806@bsu-cs.UUCP> cfchiesa@bsu-cs.UUCP (Christopher Chiesa) writes:

> >1) Centipede is a 16K cartridge and I'm just not getting all the code.
> 
> My Centipede cartridge (CXL4020) is definitely an 8k cartridge.

Hmm... I'd have sworn I'd seen two chips in there when I opened it.  Maybe I'm
thinking of something else.  But BASIC and CENTIPEDE are the ONLY two carts I 
have.  Don't have the CXLnnnn number here (I'm away from home at the moment) but
that LOOKS right...

> >       How do I get at the other 8K ?  Is there a "switch" address in the ROM
> >       that toggles in the second half "upon request"?  Or does it appear in
> >       some other, hidden memory block that I haven't found yet?

> Standard 16k cartridges occupy memory from $8000 to $BFFF.  There are two
> ROM enable lines on the cartridge connector, one for the block $8000-$9FFF
> and one for the block $A000-$BFFF.  There are also separate select lines
> for the two banks of ROM, and only enough address lines for 8k.  All this
> surely is a remnant from the design of the 800's memory.

Whaddya mean a "remnant"?  This IS an 800 I'm talking about here!  :-) 

> See "Mapping the Atari", Appendix 14, or the schematics for your system,
> for more detail.

I'd already looked at "Mapping the Atari," appendices and text; haven't looked
at the schematic though, and I don't think it would tell me anything if I did:
it's all a bunch of lines and gibberish to me...   (This is why I got OUT of 
Electrical Engineering and into Computer Science... ;-)  )
 
> Then there are the bank-switched cartridges.  Basic-XE, for instance, crams
> 16k into an 8k address space.  Switching is done by addressing locations
> $D500-$D5FF.  $Bxx addresses one block of ROM or RAM, $Axx addresses one of
> three blocks of ROM or RAM.  (I hope I got this right, haven't actually
> had a chance to play with one).
> Your cartridge definitely is not bank-switched.

I don't understand what you just said!  In fact, I'm having a devil of a time 
even explaining what it is I don't understand.  Basically that didn't make much
sense to me; could you clarify it?  What memory address controls the bank-
switching?  $D500-$D5FF is a 256-byte range, neither a single "control regis-
ter" nor an 8K block; I don't understand what appears there, under what condi-
tions.  What about "$Axx" and "$Bxx"?  Is that a value that goes into some con-
trol register, affecting what data appears at bank-switched addresses?  I'm
confused!  

> > 2) Centipede is an 8K cartridge but detects RAM-vs-ROM execution and bungs up
> >   if you've moved it to RAM.
> >
> I would be surprised if this was the case.  

Okay.  I won't waste any more time on that concept.

> >There ARE a few places in the code where an LSR (logical shift right) is per-
> >formed on memory addresses WITHIN the Cartridge ROM...
> 
> I would guess these are data areas or tables of addresses.

I suppose that could be, but I don't understand HOW.  Doing an LSR on a ROM lo-
cation doesn't affect the contents of that memory address; the only non-ROM 
data affected by an LSR, as I understand it, should be the Carry bit in the 
condition-code register.  But in this case, the LSRs (for of 'em) DON'T seem 
to be followed by anything that USES the Carry bit.  It's as inscrutable a piece
of code as I've ever seen!  I thought maybe the specified ROM address was a 
"switch" register under certain conditions...

> There are other, more innocent possibilities:
> 
> 1. During initialization the OS sets up numerous pointers based on the size
> of RAM that it finds.  Addresses $6A, $2E4-$2E6 come to mind, but there
> may be more.  To keep everything away from the cartridge code you have to set
> up all of these just right, or someone might trash part or your RAM.  

I don't understand how this would interfere.  The first thing I tried, in fact
the thing that got me started on this, was a "CARTCOPY.BAS" program that simply
copied an 8K cartridge from either slot (I have an 800) to a disk file.  It
worked fine on the Atari BASIC and Assembler/Editor cartridge, but bombed out
on Centipede.  The program comments indicated that it worked "... only for 8K
carts...", which was what led me to think Centipede might be 16K, for one thing.
But the point is, as far as can be told, the SAME DATA in the SAME ADDRESSES
WORKS when it's running from the CARTRIDGE, and DOESN'T work when running from
a disk file (or direct-copied RAM).  Does this, and your comment, imply that 
I'm not really getting the SAME DATA to DISK as is in the cartridge?  I find
that hard to believe, especially in light of the way other cartridges don't
exhibit the same behavior.

> The only
> way to be sure you are doing it right is to paw through the OS listings,
> and try to duplicate whatever is done there.

Gack.  I've been through those damn things forward and backward for the past
five YEARS without figuring out what the heck goes on in there...  I still don't
understand how the heck the WARMST and related flags work; it's still "magic"
to me and I find that incredibly frustrating.
 
On a related note, though: I've noticed that loading a binary file into RAM at 
addresses which at other times are cartridge ROM, seems to make the machine un-
happy.  I've seen innumerable programs which load, say, 7K of data into some-
where ELSE, then go to a lot of trouble to MOVE the data into, say $A000-...  
I've experimented with altering these files to load directly at $A000 in the
first place, and often as not they bomb the machine.  Why? Why? Why??  

> 2. Some OS scrolling and screen clearing routines touch memory beyond 
> the end of the screen area.  Read what "Mapping the Atari" has to say
> about location $6A for more details.  There might be some interaction
> with BUG/65 and its screen handling, too.  You might experiment with
> setting $6A (and related cells) to a value lower than $A0.  Also the
> Centipede cartridge might have routines which are doing similar sloppy
> things.

No, I took care of that first thing.  Moved the display list, screen memory
etc. well below cartridge area, and then set $6A just above my "new" memory
area.  And then didn't EXECUTE the ROM, just MOVED the data hither and yon... 

> 3. I would also be concerned about what happens to your system (and memory
> contents) when you plug and unplug a cartridge while the system is running.
> After all, you are disturbing everybody's address and data bus when you
> do that.

That's what I always thought.  But that aforementioned "CARTCOPY.BAS" program 
used this technique and simply said "if the machine locks up, reboot and try
again."  It seems to be a matter of getting the cartridge in STRAIGHT, FAST,
and ALL THE WAY.  Any "tilting" of the cart so that one end of the bus enga-
ges before the other, sends the machine off into la-la land.  But the computer
doesn't seem any the worse...  What exactly am I risking, besides locking up
the current "session"?  Is there a better method? 

> 
> Happy hunting,
> 
> Hans

Thanks!  I appreciate your taking the time to comment.  You've been most
helpful!

Chris
-- 
UUCP: <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!cfchiesa 
cfchiesa@bsu-cs.UUCP                                           

hans@umd5.umd.edu (Hans Breitenlohner) (05/21/88)

> 
Apparently I did not describe things real well on my last try, so here we go
again:
> Hmm... I'd have sworn I'd seen two chips in there when I opened it.  Maybe I'm
Yes, there are two chips, but they are both 4k ROMs.  Maybe these were cheaper
than the 8k variety at the time, or maybe one half contains subroutines
common to several games.  The key thing is that they both are selected by the
S5 signal, which indicates the address range $A000-$BFFF.  16k cartridges
(with a flat 16k address space) will also use the RD4 and S4 signals, and
bank switched cartridges will use the CCTL signal.  The Centipede cartridge
does not even have contacts in these locations.  (See 'Mapping the Atari',
Appendix 14, for the pinout of the cartridge connector.
> 
> 
> Whaddya mean a "remnant"?  This IS an 800 I'm talking about here!  :-) 
Sorry, I did not mean to offend you.  But when you look at this from the point
of view of an XL or XE, this addressing scheme might seem strange.
> 
> I don't understand what you just said!  In fact, I'm having a devil of a time 
> even explaining what it is I don't understand.  Basically that didn't make much
> sense to me; could you clarify it?  What memory address controls the bank-
> switching?  $D500-$D5FF is a 256-byte range, neither a single "control regis-
> ter" nor an 8K block; I don't understand what appears there, under what condi-
> tions.  What about "$Axx" and "$Bxx"?  Is that a value that goes into some con-
> trol register, affecting what data appears at bank-switched addresses?  I'm
> confused!  
> 
The i/o area address space $D500-$D5FF is decoded in the Atari, and the 
result is fed to the cartridge as the CCTL line.  This apparently was meant
for such applications as bank switching, and for cartridges with i/o devices.
After that it is up to the cartridge what to do with it.  
The scheme I described is used by the OSS cartridges (Basic XL and XE,
Mac/65, and maybe Action, too).   In the more common approach you would
store a value xx in a control register to accomplish a certain action.
In this scheme, instead, you reference location $D5xx.  
This probably simplified hardware design.
So, for instance, a reference to $D500 selects bank 0, $D501 selects bank
1, and so on.  Since these may be store instruction, this can be done without
affecting registers, which may simplify programming.
Where I referred to $Axx and $Bxx, that should have been $Axxx and $Bxxx,
to indicate that these cartridges treat the two halves of their address
space separately.

> > >There ARE a few places in the code where an LSR (logical shift right) is per-
> > >formed on memory addresses WITHIN the Cartridge ROM...
> > 
> > I would guess these are data areas or tables of addresses.
> 
> I suppose that could be, but I don't understand HOW.  Doing an LSR on a ROM lo-
> cation doesn't affect the contents of that memory address; the only non-ROM 
What I suggestes was that these areas are not really code, but data used for
displays or whatever.  After all, if you disassemble arbitrary data you some-
times get what looks like real instruction sequences.  On the other hand, 
if these LSR instructions are in the middle of what appears to be legitimate
code, then I was probably wrong, and this is some form of copy-protection.
You might try replacing these instructions with SEC or CLC, as appropriate.
> > 1. During initialization the OS sets up numerous pointers based on the size
> > of RAM that it finds.  Addresses $6A, $2E4-$2E6 come to mind, but there
> > may be more.  To keep everything away from the cartridge code you have to set
> > up all of these just right, or someone might trash part or your RAM.  
> 
> I don't understand how this would interfere.  The first thing I tried, in fact
> the thing that got me started on this, was a "CARTCOPY.BAS" program that simply
> copied an 8K cartridge from either slot (I have an 800) to a disk file.  It
> worked fine on the Atari BASIC and Assembler/Editor cartridge, but bombed out
> on Centipede.  The program comments indicated that it worked "... only for 8K
> carts...", which was what led me to think Centipede might be 16K, for one thing.
> But the point is, as far as can be told, the SAME DATA in the SAME ADDRESSES
> WORKS when it's running from the CARTRIDGE, and DOESN'T work when running from
> a disk file (or direct-copied RAM).  Does this, and your comment, imply that 
> I'm not really getting the SAME DATA to DISK as is in the cartridge?  I find
> that hard to believe, especially in light of the way other cartridges don't
> exhibit the same behavior.
> 
You are probably right on this one, but let me explain my point.  When you 
boot without cartridge, the OS sets up numerous pointers to reflect a 
memory size of 48k.  When you boot with a cartridge, those pointers are set
up for a memory size of 40k.  When you boot without cartridge, and then want
to run the equivalent of a cartridge, you have to change those pointers.  My
point was that if you do not make all the changes needed, then some
cartridges may run, and others may not, depending on which pieces of infor-
mation they use.  And of various pieces of code that I have looked at, I have
not seen one yet that set all of these things correctly.

> On a related note, though: I've noticed that loading a binary file into RAM at 
> addresses which at other times are cartridge ROM, seems to make the machine un-
> happy.  I've seen innumerable programs which load, say, 7K of data into some-
> where ELSE, then go to a lot of trouble to MOVE the data into, say $A000-...  
> I've experimented with altering these files to load directly at $A000 in the
> first place, and often as not they bomb the machine.  Why? Why? Why??  
I can't think of any reason why that should be so, but have made the same
observation at times.  Never had the time to chase it down, though.
> 
> doesn't seem any the worse...  What exactly am I risking, besides locking up
> the current "session"?  Is there a better method? 
Apparently lockups are all you are risking.  If you are going to do a lot
of this, a switch in the S5 line would make the cartridge appear and
disappear, while keeping the memory occupied at all times.  You could add
that either in the cartridge or in your 800.

> 
> 
> Thanks!  I appreciate your taking the time to comment.  You've been most
> helpful!
>
> Chris
>
You are welcome.  This has been a fun project to pursue, and I don't even
have to do any of the work!

Hans