[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: AUX memory question



Dennis Jenkins <dennis@usb.com> wrote:

> David Empson wrote:
> > See TN.PDOS.026 (Polite Use of Auxiliary Memory) for details.
> 
> What is the URL of this document?

It doesn't look like Apple have the Apple II technotes on their FTP
server any longer, but I expect they will be available on one of the
archive sites (ground, for example).  Have a look through the FAQs for
pointers to them.

Assuming Apple's organisation is retained, there should be a TN.About
and TN.Index file at the root level (plus FTN.About and FTN.Index), with
a subdirectory for each technote category.  The "PDOS" subdirectory
contains ProDOS-8 technical notes, and the individual files are named
TN.PDOS.nnn (nnn is the technote number), similarly for other
categories.

The technote isn't critical - it just explains the rules for using
auxiliary memory areas in different circumstances.  You also need the
ProDOS-8 Technical Reference (memory map near the end) so that you can
identify the normally reserved areas.

> Maybe I should start from the top.  This is what I want:
> 
> 1) I am developing a prodos application (SYS file).
> 2) I am using the CC65 cross compiler.  My code is a mix of asm and C.
> 3) I use $800->$1fff (main) to store prodos buffers.
> 4) I use the 80 column text screen and sometimes double low-res
> graphics.
> 5) I wish to use as much of AUX memory (from $800->$feff ??) to store
>    a fairly large byte array in.  As far as my C code is concerned, I
>    will be accessing this memory from wrapper functions:
>      unsigned char ReadAuxMemory(void *ptr);
>      void WriteAuxMemory(void *ptr, unsigned char c);

You should be able to use up to $FFF9 safely, and can probably get away
with $FFFA through $FFFD, but should avoid $FFFE-$FFFF.

$FFFE-$FFFF in the auxiliary language card should be set to the same
value as in the ROM.  This will allow interrupts to be handled correctly
on the IIc and enhanced IIe.  (As mentioned earlier, this is not an
issue on the IIgs.)  The unenhanced IIe can't handle interrupts with the
auxiliary language card active, but you aren't all that likely to have
an interrupt source on a IIe.

You can minimise problems by ensuring interrupts are locked out at all
times while the auxiliary zero page/stack/language card are switched in.

> 6) In general, I will not be executing any code in AUX memory, just
>    the minimum code required to read or write bytes.
> 7) I can deal with the memory hole at $c000->$cfff.

One convenient way of dealing with this area would be if your routine
pretended that the second $D000-$DFFF bank was located in $C000-$CFFF.

> Currently, I load two 9 byte stubs into main memory at $e0 -> $f3.  I
> have asm wrappers that pop my C args from the virtual stack (it is what
> cc65 uses for passing args).  These functions test my argument ranges,
> then call the appropriate read/write function at $e0 or $e9.  These
> functions just store the accumulator to the softswitch $c002/$c004 (as
> required), lda/sta my byte, then set the softswitch back to main memory,
> then return to the caller.

OK, that code will work fine for $0800-$BFFF, but it won't work for the
auxiliary language card area ($D000-$FFFF or the second bank in
$D000-$DFFF), because you need to use different soft-switches, and
switching in the auxiliary language card will switch out the main memory
zero page (and stack).

If you haven't already used the $0200-$03DF area in main memory, I
suggest adding four stub routines in there which will deal with the
auxiliary language card area (read bank 1, write bank 1, read bank 2,
write bank 2).

Your main ASM wrapper code should check for three address ranges:

$0800-$BFFF go to your existing zero-page routine.
$C000-$CFFF go to the read/write aux bank 1 routine, with the high byte
            patched by adding $10 (thus $C000-$CFFF map to $D000-$DFFF).
$D000-$FFF9 go to the read/write bank 2 routine, with an unpatched high
            byte.

(You can use either bank 1 or 2 to access $E000-$FFFF.  It is only the
$D000-$DFFF area which changes according to the bank selection.)

The stub routines to access the auxiliary language card area are as
follows:

RDAUX1   SEI                ; No interrupts!
         LDX C088           ; Read-enable language card bank 1
         STA C009           ; Switch in auxiliary language card, etc.
         LDA xxxx           ; Read target location (patched)
         STA C008           ; Switch in main language card, etc.
         LDX C08A           ; Switch the ROM back in
         CLI                ; Enable interrupts
         RTS

WRAUX1   SEI                ; No interrupts!
         LDX C08B           ; Read/write language card bank 1
         LDX C08B           ; (must access twice)
         STA C009           ; Switch in auxiliary language card, etc.
         STA xxxx           ; Write target location (patched)
         STA C008           ; Switch in main language card, etc.
         LDX C08A           ; Switch the ROM back in
         CLI                ; Enable interrupts
         RTS

RDAUX2   SEI                ; No interrupts!
         LDX C080           ; Read-enable language card bank 2
         STA C009           ; Switch in auxiliary language card, etc.
         LDA xxxx           ; Read target location (patched)
         STA C008           ; Switch in main language card, etc.
         LDX C082           ; Switch the ROM back in
         CLI                ; Enable interrupts
         RTS

WRAUX2   SEI                ; No interrupts!
         LDX C083           ; Read/write language card bank 2
         LDX C083           ; (must access twice)
         STA C009           ; Switch in auxiliary language card, etc.
         STA xxxx           ; Write target location (patched)
         STA C008           ; Switch in main language card, etc.
         LDX C082           ; Switch the ROM back in
         CLI                ; Enable interrupts
         RTS

The C008/C009 switch controls both read and write access, unlike the
switches for the main $0200-$BFFF area, but note the different
instruction sequences needed to control read enable and read/write
enable for the language card area.  (You could set up the language card
for write-only access using C081 or C089 instead of C083 or C08B, but it
won't make the code any shorter.)

> I do disconnect /RAM, and I don't care if /RAM is to be re-attached when
> I'm done.

Are you sure about that?  If your application disconnects /RAM, then it
is the responsibility of your application to reconnect it again when you
terminate.  The only reasonable exceptions to this would be an
application which installs its own replacement RAM disk driver, or a
special-purpose application which never quits.

The /RAM volume is there for the convenience of the user.  If you don't
restore it, then subsequent applications which need to use it won't be
able to, and some application won't be able to use auxiliary memory at
all if there is no /RAM volume present (others might assume that they
have full rein, and overwrite anything you might have left there).
.