Introducing 0840 EconoBanking
I've just built a cart using a new low-cost 8K banking scheme. Unlike other 8K designs which either require a programmable logic device or multiple logic chips, this design uses one 16-pin DIP, a 2.2K resistor, and a 100pF cap (and an EPROM of course). The one limitation is that code must be written to use the new banking method--it's not F8-compatible. Writing games to be easily-adaptable to both formats, however, should not be difficult. Any address $0800-$0FFF (or $2800-$2FFF, $4800-$4FFF, etc.) will trigger a switch to the bank specified on A6. Use $0800 to switch one way, and $0FFF to switch the other.
74x153 or 74x253 . +---------+ . Gnd-----|/G1 VDD|-----VCC . VCSA12--|B /G2|-----Gnd . Gnd-----|1C3 A|-----A11 . Gnd-----|1C2 2C3|--. . VCC-----|1C1 2C2|--+ . VCC-----|1C0 2C1|--|--A6 . /CS-----|1Y 2C0|--+----+--EA12 . Gnd-----|VSS 2Y|----R--+--C--Gnd . +---------+
I justed tested an 8K version of Hack'Em on this cart and it works great. Asteroids, however, is flaky. That game makes some bogus memory accesses around $48xx-$4FFF. Such accesses are harmless in an F8 cart, but trigger bankswitching on this one. Still, if a game is written to avoid stray memory accesses, it should be easy to adapt it to either F8 or 0840 banking.
Care should be exercised when using "BIT abs" or "NOP abs" to skip over a two-byte instruction, since those instructions will perform a memory read. For example, using a NOP to skip over "LDA #$08" will cause a read of $08A9, triggering a switch to bank zero. These hazards may be mitigated by ensuring that any code that might trigger a bankswitch is already in the bank that would be selected. For example, any code which skips over an LDA instruction should be in bank zero.
If portability to F8 carts isn't a concern, games that need to access a lot of ROM data within the kernel may switch banks at minimal cost. A switch to bank 0 or 1 may be combined with any TIA access. Additionally, an access to memory $0080-$00BF may be combined with a switch to bank 0, and an access to $00C0-$00FF may be combined with a switch to bank 1. For example:
; A copy of this routine should be present, at the same address, in both banks. sta $0800+WSYNC; Wait for sync and switch to bank 0 lda PF0data,x ; Fetches from bank 0 sta $0840+PF0 ; Stores it and switches to bank 1 (4 cycles) lda PF1data,x ; Fetches from bank 1 sta PF1 ; Just store to PF1 (three cycles)--still in bank 1
Not sure there's going to be a lot of need for this sort of trick, but 0840 banking does allow it.