›››› XE-Bank Programmer's Manual› › Copyright 1992 by Duane Tribe› July 19, 1992› › › OVERVIEW› › This package provides CC65 programs access to the 64K of extended› memory in an Atari 130XE or compatibly-expanded Atari computer as an› alternate memory space. Although the access may be slow, the routines› enable C programs to perform many new and larger tasks.› › The routines are grouped into several object files; see the User's› Manual for descriptions of each routine.› › › XE MEMORY LAYOUT› › The XE memory is organized as 4 banks of 16K bytes each. To access› one of the banks, main memory from 0x4000 to 0x7FFF is replaced by the› XE memory bank. This memory range is the "access window".› › The routines are limited to just 64K because CC65 cannot directly› manipulate values larger than 16 bits.› › The bits in the address are interpreted as:› › BBAA AAAA AAAA AAAA› › where› BB - Bank number (0..3)› AA AAAA AAAA AAAA - Address in bank (0..16383)› › This is converted to a bank selection byte:› › 1110 BB11› › and an address in main memory:› › 01AA AAAA AAAA AAAA› › › DYNAMIC MEMORY› › Memory blocks are allocated from a linked list of free blocks. The› word _freelis points to the first free block. The list then› progresses linearly up through the XE memory space.› › Blocks are allocated by finding the first free block that is as large› as or larger than the requested block. If the block that is chosen is› at least 4 bytes larger than the request, the excess bytes are split› off as a new free block.››››››› 1››››››› › Each block, either allocated or free, is composed as:› › +-- Address of block› |› v› SS NN...› › where› SS - Size of the block (2 to 65534)› NN - Address of next free block (if in the free list)› NN... - Data bytes (if the block is in use)› › Every block has a "size" word (SS) just before the block's address. › If the block is in the free list, the first two data bytes (NN) are› used as a pointer to the next free block. A NULL pointer indicates› the end of the free block list.› › Thus, there is a 2-byte overhead per block, with a minimum of 4 bytes› total used per block. The size of the block is only limited by how› much contiguous unused memory is available.› › The block release routine, xfree(), automatically merges adjacent free› blocks. But as blocks are allocated and only some released, the XE› memory space may become fragmented. The user can reduce fragmentation› by allocating long-term use memory blocks first.› › › 6502 SUBROUTINES› › This is a set of machine language subroutines used by the C routines› to access the XE memory.› › The calling routine must swap in the appropriate XE bank into the› access window as needed and return main memory to that window before› exiting. These subroutines must not be called by routines under the› access window.› › The routines access XE memory bytes through two sets of zero-page› pointers and bank numbers: xbank1 and xaddr1, or xbank2 and xaddr2. › The bytes xbank1 and xbank2 are the bank number along with other bits› for the PIA port. The 2-byte pointers xaddr1 and xaddr2 are the› corresponding addresses within the access window.› › These symbols are not resolved by the linking process:› › xbase = $96› xaddr1 = $98› xbank1 = $9A› xaddr2 = $9B› xbank2 = $9D› › Each of the routines returns with the 6502 A and X registers››››››› 2››››››› scrambled. The value in the Y register remains intact.› › xpoint› › ldy #[addr flag]› jsr xpoint› › Convert 16-bit XE memory address in xbase to a bank number and access› window address. If Y (the 6502 Y register) is 0, the data are stored› at xbank1 and xaddr1; if Y is 3, then xbank2 and xaddr2 are used› instead.› › Does not actually bring the bank into view; see Access Window Control› below.› › xincr› › ldy #[addr flag]› jsr xincr› › If Y is 0, increments xaddr1,xaddr1+1 to point to next byte in the› XE-bank access window. If the address is beyond the access window,› the address is wrapped back to the start of the window and xbank1 is› incremented. If Y is 3, then xbank2 and xaddr2 are used instead.› › If the address crosses a 16K boundary, the new bank will be placed in› the access window, even if main memory was in the access window.› › xdecr› › ldy #[addr flag]› jsr xdecr› › If Y is 0, decrements xaddr1,xaddr1+1 to point to next byte in the› XE-bank access window. If the address is beyond the access window,› the address is wrapped back to the end of the window and xbank1 is› decremented. If Y is 3, then xbank2 and xaddr2 are used instead.› › If the address crosses a 16K boundary, the new bank will be placed in› the access window, even if main memory was in the access window.› › Access Window Control› › To swap the bank in xbank1 into the access window, use› › lda xbank1› sta $D301› › To swap the bank in xbank2 into the access window, use› › lda xbank2› sta $D301› ››››››› 3››››››› To return main memory to the access window, use› › lda #$F3› sta $D301› › Example› › To reference the byte at 0x1234 in XE memory:› › lda #$34› sta xbase› lda #$12› sta xbase+1› › ldy #0› jsr xpoint› › lda xbank1› sta $D301› › lda (xaddr1),y› › Do not reference subsequent bytes by incrementing Y unless you can be› sure that the target address will not fall outside the access window. › Instead, use xincr:› › jsr xincr› lda (xaddr1),y› › xincr will handle the necessary bank swapping when crossing the bank› boundaries at 0x0000, 0x4000, 0x8000, and 0xC000.› › In this example it was not necessary to call xpoint. The xbank1 and› xaddr1 values could have been computed by hand and stored directly:› › lda #$E3 ; bank 0› sta xbank1› lda #$52 ; $12 into window› sta xaddr1+1› lda #$34 ; low byte› sta xaddr1› › Remember to return main memory to the access window before attempting› to access main memory that may reside under the window.› ››››››››››››››› 4›››