0071-007F, 00F4-00FF | Zero-page hotspots. Bank-switch modes may be selected by reading or writing addresses in this range. |
0400-0FFF | Soft-switch hotspots. A read access to any of these addresses will trigger a mode switch *IF* the last byte fetched before the read was $60-$6F. Note that when using most addressing modes, this effectively means that the hotspots will appear at $6400-$6FFF but not at any other "mirrors" of those addresses. Not all addresses in this range are used; access to any unused address in the $6400-$6FFF range is forbidden. Although the cartridge will respond to the $6400-$6FFF hotspots, it will not output any data on the bus, so the data read will be likely be meaningless. |
1000-17FF | This 2K region may access any 2K region of RAM, or of the first 32K of ROM. |
1800-1DFF | This 1.5K region may access the first 1.5K of any 2K region of RAM, or of the last 32K of ROM. |
1E00-1EFF | This 256-byte region may point to any 256-byte page of RAM or ROM. |
1F00-1FFF | This 256-byte region will always access the last 256 bytes of ROM. If accessed at addresses $7F00-$7FFF, these addresses will also act as a "hi-res helper" hotspots. |
Address-triggered: switch upper bank | |||||||||||||||||||||||||||||||||||||||
$6C00-$6CFF | Enable page 0-255 of ROM at $1E00-$1EFF | ||||||||||||||||||||||||||||||||||||||
$6D00-$6D7F | Enable page 0-127 of RAM at $1E00-$1EFF | ||||||||||||||||||||||||||||||||||||||
Address-triggered: switch lower bank | |||||||||||||||||||||||||||||||||||||||
$6E00-$6E0F | Enable block 0-15 of ROM at $1000-$17FF | ||||||||||||||||||||||||||||||||||||||
$6E40-$6E4F | Enable block 0-15 of RAM at $1000-$17FF | ||||||||||||||||||||||||||||||||||||||
Other $6Exx | Forbidden. | ||||||||||||||||||||||||||||||||||||||
Address-triggered: switch middle bank
$6F10-$6F1F
| Enable block 16-31 of ROM at $1800-$1DFF
| $6F40-$6F4F
| Enable block 0-15 of RAM at $1800-$1DFF
| Other $6Fxx
| Forbidden.
| Address-triggered hires helper functions
| $7F00-$7FFF
| Copy bit 3 of address into A11 of first block address and bits 4-6 of
address into A8-A10 of first block address. Bits 0-2 and 7 are ignored.
| Address-triggered Stella helper functions | Note that these functions shadow the TIA or low-RAM addresses, so these bank switches may be performed simultaneous with a TIA or low-RAM read or write. Note that zero-page hotspots will not be triggered by these accesses. $6400-$64FF
| Toggle bit A11 of the lower block address
| $6500-$65FF
| Toggle bit A12 of the lower block address
| $6800-$68FF
| Toggle bit A11 of the middle block address
| $6900-$69FF
| Toggle bit A12 of the middle block address
| Data-based zero-page bankswitch functions | These are the only hotspots that use the written data. Unlike the other hotspots, these locations may not be protected against stray accesses so use caution. The $00Fx addresses may be read or written freely; the $7x ones may be written only. The last value read or written will be the one that's used. $F4,$F6,$FC,$FE
| Select the specified page of flash to appear at address $1E00.
| $F5,$F7,$FD,$FF
| Select the specified page of RAM to appear at address $1E00.
| $F8,$F9,$FA,$FB
|
If data is 0000nnnn: Select block 0nnnn of flash into lower address block | If data is 0100nnnn: Select block nnnn of RAM into lower address block If data is 1001nnnn: Select block 1nnnn of flash into middle address block If data is 1100nnnn: Select block nnnn of RAM into middle address block $74-$7F
| Write-only addresses trigger the same bank switches as the addresses
$0080 bytes higher, but without affecting the preset RAM. It is recommended
that only $7B, $7C, and $7D be used.
| Optional LED control | If the optional LEDs are installed, any read or write from these addresses will switch them on or off as indicated. $0071 | Turn both LEDs off
| $0072 | Turn the red LED on and the green LED off
| $0073 | Turn the green LED on and the red LED off
| |
Each of the memory presets will function both as a bank-switch trigger and as a byte of normal RAM. Because of this dual functionality, it's possible to switch among a small group of banks fairly quickly--simply store their page or block addresses into the hotspots first, then read them via the "NOP zp" instruction to select them. The four addresses within each group will behave interchangeably as far as bank-switching is concerned, but are 'backed' by four different bytes of RAM.
Note that accessing these bytes of RAM will trigger bankswitches only if the accesses are done in page zero (or, more precisely, when A8-A12 are all zero, since the cartridge can't see A13-A15). Thus, it is possible to store values into these RAM locations without triggering bank switching by storing at a shadow address ($01F4-$01FF is the recommended choice). The CLEAN_START macro commonly used with DASM actually does its stores in the $0100-$01FF range, and will thus not trigger any bankswitching.
Table setup
$7F00: Sixteen 00 bytes, then 12 copies of (01 02 04 08 10 20 40 80),
then eight 00 bytes, then eight code bytes (see below).
$7F80: Sixteen FF bytes, then 12 copies of (FE FD FB F7 EF DF BF 7F),
then eight 00 bytes, then eight bytes for vectors etc.
Pixel plotting/erasure
; Plot pixel at X,Y lda $7F00,x ora $1E00,y sta $1E00,y ; Erase pixel at X,Y lda $7F80,x and $1E00,y sta $1E00,yNote that plotted pixels will go into pages 1-6 of a 2K bank; if the X coordinate stays within the range 0-119, pages 0 and 7 will be unaffected.
Code may be run from $1E00-$1EFF, but such code should not make any access to the $1F00-$1FFF memory page, whether at the hotspot address or not.
Bulk memory copying
Although for some purposes, the larger banks are convenient, the 256-byte size of the smaller page can often be an asset in its own way.
; Copy some pages of data from flash to RAM. ; The MSB of the source address is in X ; The MSB of the destination address is in Y ; The number of pages is in the accumulator. stx $FE sty $FF sec bcs entry2 loop1: ldx #0 pha loop2: nop $FE ; Use source page lda $1E00,x ldy $1E80,x nop $FF ; Use destination page sta $1E00,x sty $1E80,x inx bpl loop2 pla inc $FE inc $FF entry2: sbc #1 bcs loop1Perhaps the most interesting thing to note here is that the bank switches were performed without having to load the page addresses into registers. There are twelve zero-page bank-switching hotspots; one may freely switch banks using them merely by reading them.
It should be noted that the hotspots $00F4-$00FF use the same RAM as $01F4-$01FF, but reads or writes to the latter range of addresses will not trigger hotspots. Thus, if a programmer wishes to use only the top six hotspot addresses, the stack pointer may safely be set to $F9. Pushes and pops to/from addresses $01F4-$01F9 will not trigger bank switching.
High-resolution shape drawing
These simple code bits for drawing/erasing pixels may easily be used to draw larger shapes. The following, for example, might be used to draw explosions in a Stella-sketch-kernel missile defense game (this code is quite similar to what I use in my Minigame entry, except that I call subroutines for pixel plotting).
; Draw a hexagon with diagonal sides of length 'size' and vertical sides of ; length 'size'*2. Assumes X,Y is at center. ; First find a few y values we'll need and then move to the bottom tya sec sbc size sta temp2 sbc size sta temp3 tya clc adc size sta temp1 adc size sta temp4 tay ; Now draw up bottom-right edge lp1: lda $7F00,x ora $1E00,y sta $1E00,y dey lda $7F00,x ora $1E00,y sta $1E00,y inx cpy temp1 bne lp1 ; Now draw up right-hand side lp2: lda $7F00,x ora $1E00,y sta $1E00,y dey lda $7F00,x ora $1E00,y sta $1E00,y dey cpy temp2 bne lp2 ; Now draw up the top-right edge lp3: lda $7F00,x ora $1E00,y sta $1E00,y dey lda $7F00,x ora $1E00,y sta $1E00,y dex cpy temp3 bne lp3 ; Now draw down top-left edge lp4: lda $7F00,x ora $1E00,y sta $1E00,y iny lda $7F00,x ora $1E00,y sta $1E00,y dex cpy temp2 bne lp4 ; Now draw down left-hand side lp5: lda $7F00,x ora $1E00,y sta $1E00,y iny lda $7F00,x ora $1E00,y sta $1E00,y iny cpy temp1 bne lp5 ; Now draw down bottom-left edge lp6: lda $7F00,x ora $1E00,y sta $1E00,y iny lda $7F00,x ora $1E00,y sta $1E00,y inx cpy temp4 bne lp6Not sure if I got all the terminating cases right, but examination of the code will reveal that it's pretty simple for a polygon-draw procedure WITH NO SUBROUTINE CALLS. The code moves from one point to the next with nothing more than an 'iny', 'inx', 'dey', or 'dex. Makes rapid drawing of shapes a snap.