diff --git a/BizHawk.Emulation/Consoles/Atari/docs/Atari_Mappers.txt b/BizHawk.Emulation/Consoles/Atari/docs/Atari_Mappers.txt new file mode 100644 index 0000000000..3a97441c0b --- /dev/null +++ b/BizHawk.Emulation/Consoles/Atari/docs/Atari_Mappers.txt @@ -0,0 +1,1409 @@ +Copied from: +http://blog.kevtris.org/blogfiles/Atari%202600%20Mappers.txt + +Mostly Inclusive Atari 2600 Mapper / Selected Hardware Document +--------------------------------------------------------------- + +03/04/12 +Kevin Horton aka kevtris +--- + +Version 1.00 + + +Things covered in this document: +-------------------------------- + +"original" mappers from when the system was in production: + +2K +4K +CV (Commavid) +F8 (Atari 8K) +F6 (Atari 16K) +F4 (Atari 32K) +FE (Activision 8K) +E0 (Parker bros. 8K) +3F (Tigervision 8K) +FA (CBS RAM Plus 12K) +E7 (M-network 16K) +F0 (Megaboy 64K) +UA (UA Ltd 8K) + +"homebrew" mappers which are more recent: + +3F (Enhanced Tigervision style, up to 512K) +3E (up to 512K of ROM, 256K of RAM) +0840 (Econobanking) +MC (Megacart) +EF (16K) +X07 (Atariage) +4A50 (no name) + +Atari 2600 peripherals: + +Spectravideo Compumate +Pitfall 2 DPC +Supercharger +Supercharger tape format +Supercharger demo unit + + +--- + + +"original" 2600 Mappers +----------------------- + +2K (no name) +----- + +2K of ROM. no bankswitching. + +4K (no name) +----- + +4K of ROM. no bankswitching. + +CV Commavid +----- + +This was used by Commavid. It allowed for both ROM and RAM on the cartridge, +without using bankswitching. There's 2K of ROM and 1K of RAM. + +2K of ROM is mapped at 1800-1FFF. +1K of RAM is mapped in at 1000-17FF. + +The read port is at 1000-13FF. +The write port is at 1400-17FF. + +F8 (Atari style 8K) +----- + +This is the fairly standard way 8K of cartridge ROM was implemented. There are two +4K ROM banks, which get mapped into the 4K of cartridge space. Accessing 1FF8 or +1FF9 selects one of the two 4K banks. When one of these two addresses are accessed, +the banks switch spontaniously. + +ANY kind of access will trigger the switching- reading or writing. Usually games use +LDA or BIT on 1FF8/1FF9 to perform the switch. + +When the switch occurs, the entire 4K ROM bank switches, including the code that is +reading the 1FF8/1FF9 location. Usually, games put a small stub of code in BOTH banks +so when the switch occurs, the code won't crash. + +F6 (Atari style 16K) +----- + +This is a fairly standard 16K bankswitching method. It works like F8, except there's +four 4K banks of ROM, selected by accessing 1FF6 through 1FF9. These sequentially +select one of the 4 banks. i.e. 1FF6 selects bank 0, 1FF7 selects bank 1, etc. + +F4 (Atari style 32K) +----- + +Again, this works like F8 and F6 except now there's 8 4K banks. Selection is performed +by accessing 1FF4 through 1FFB. + +FE (Activision special) +----- + +Activision used this method on only three games: Decathlon, Robot Tank, and the +prototype Thwocker. This mapper is one of the more interesting ones in that it uses +stack access to select banks. It is composed of two 4K banks, similar to F8. +Unlike F8, however, switching occurs when the stack is accessed. + +This mapper allows for "automatic" bankswitching to occur, using JSR and RTS. The +addresses for all JSRs and RTS' are either Fxxx or Dxxx, and the mapper uses this to +figure out which bank it should be going to. + +The cycles of a JSR are as such: + +1: opcode fetch +2: fetch low byte of address +3: read 100,s : garbage fetch +4: write 100,s : PCH, decrement S +5: write 100,s : PCL, decrement S +6: fetch high byte of address + +The cycles of an RTS are as such: + +1: opcode fetch +2: fetch next opcode (and throw it away) +3: read 100,S : increment S +4: read 100,S : pull PCL from stack, increment S +5: read 100,S : pull PCH from stack + +The chip can determine what instruction is being executed by watching the data and +address bus. + +It watches for 20 (JSR) and 60 (RTS), and accesses to 100-1ff: + +(opcode cycles) + +20 (opcode) +add low (new add low) +stack (garbage read) +stack (push PCH) +stack (push PCL) +add high (new add hi) : latch D5. This is the NEW bank we need to be in. + +60 (opcode) +xx (garbage fetch) +stack +stack (pull PCL) +stack (pull PCH) : latch D5. This is the NEW bank we need to be in. + + +Using emulators or similar there is a large cheat that can be used. A13 can be used +to simply select which 8K bank to be in. + +E0 (Parker Bros) +----- + +Parker Brothers used this, and it was used on one other game (Tooth Protectors). It +uses 8K of ROM and can map 1K sections of it. + +This mapper has 4 1K banks of ROM in the address space. The address space is broken up +into the following locations: + +1000-13FF : To select a 1K ROM bank here, access 1FE0-1FE7 (1FE0 = select first 1K, etc) +1400-17FF : To select a 1K ROM bank, access 1FE8-1FEF +1800-1BFF : To select a 1K ROM bank, access 1FF0-1FF7 +1C00-1FFF : This is fixed to the last 1K ROM bank of the 8K + +Like F8, F6, etc. accessing one of the locations indicated will perform the switch. + +3F (Tigervision) +----- + +Traditionally, this method was used on the Tigervision games. The ROMs were all 8K, and +there's two 2K pages in the 4K of address space. The upper bank is fixed to the last 2K +of the ROM. + +The first 2K is selectable by writing to any location between 0000 and 003F. Yes, this +overlaps the TIA, but this is not a big deal. You simply use the mirrors of the TIA at +40-7F instead! To select a bank, the games write to 3Fh, because it's not implemented +on the TIA. + +The homebrew community has decided that if 8K is good, more ROM is better! This mapper +can support up to 512K bytes of ROM just by implementing all 8 bits on the mapper +register, and this has been done... however I do not think 512K ROMs have been made just +yet. + +FA (RAM Plus) +----- + +CBS Thought they'd throw a few tricks of their own at the 2600 with this. It's got +12K of ROM and 256 bytes of RAM. + +This works similar to F8, except there's only 3 4K ROM banks. The banks are selected by +accessing 1FF8, 1FF9, and 1FFA. There's also 256 bytes of RAM mapped into 1000-11FF. +The write port is at 1000-10FF, and the read port is 1100-11FF. + +E7 (M-Network) +----- + +M-network wanted something of their own too, so they came up with what they called +"Big Game" (this was printed on the prototype ASICs on the prototype carts). It +can handle up to 16K of ROM and 2K of RAM. + +1000-17FF is selectable +1800-19FF is RAM +1A00-1FFF is fixed to the last 1.5K of ROM + +Accessing 1FE0 through 1FE6 selects bank 0 through bank 6 of the ROM into 1000-17FF. +Accessing 1FE7 enables 1K of the 2K RAM, instead. + +When the RAM is enabled, this 1K appears at 1000-17FF. 1000-13FF is the write port, 1400-17FF +is the read port. + +1800-19FF also holds RAM. 1800-18FF is the write port, 1900-19FF is the read port. +Only 256 bytes of RAM is accessable at time, but there are four different 256 byte +banks making a total of 1K accessable here. + +Accessing 1FE8 through 1FEB select which 256 byte bank shows up. + +F0 (Megaboy) +----- + +This was used on one game, "megaboy".. Some kind of educational cartridge. It supports +64K of ROM making it the biggest single production game made during the original run +of the 2600. + +Bankswitching is very simple. There's 16 4K banks, and accessing 1FF0 causes the bank +number to increment. + +This means that you must keep accessing 1FF0 until the bank you want is selected. Each +bank is numbered by means of one of the ROM locations, and the code simply keeps accessing +1FF0 until the bank it is looking for comes up. + + +UA (UA Ltd) +----- + +This one was found out later on, lurking on a proto of Pleaides. It works with 8K of ROM +and banks it in 4K at a time. + +Accessing 0220 will select the first bank, and accessing 0240 will select the second. + + +That's about it for the "Traditional" mappers that were used on commercial releases. + +----------------------------------- + +The 2600 programming community's been pretty busy with adding new mappers. Here's the list +of known (to me) mappers used on homebrew games. + +3E (Boulderdash +----- + +This works similar to 3F (Tigervision) above, except RAM has been added. The range of +addresses has been restricted, too. Only 3E and 3F can be written to now. + +1000-17FF - this bank is selectable +1800-1FFF - this bank is the last 2K of the ROM + +To select a particular 2K ROM bank, its number is poked into address 3F. Because there's +8 bits, there's enough for 256 2K banks, or a maximum of 512K of ROM. + +Writing to 3E, however, is what's new. Writing here selects a 1K RAM bank into +1000-17FF. The example (Boulderdash) uses 16K of RAM, however there's theoretically +enough space for 256K of RAM. When RAM is selected, 1000-13FF is the read port while +1400-17FF is the write port. + +0840 (Econobanking) +----- + +This is another 8K bankswitching method with two 4K banks. The rationale is that it's +cheap and easy to implement with only a single 74HC153 or 253 dual 4:1 multiplexer. + +This multiplexer can act as a 1 bit latch AND the inverter for A12. + +To bankswitch, the following mask it used: + +A13 A0 +---------------- +0 1xxx xBxx xxxx + +Each bit corresponds to one of the 13 address lines. a 0 or 1 means that bit must be +0 or 1 to trigger the bankswitch. x is a bit that is not concidered (it can be either +0 or 1 and is thus a "don't care" bit). + +B is the bank we will select. sooo, accessing 0800 will select bank 0, and 0840 +will select bank 1. + +SB (Superbanking) +----- + +This is the same as 0840, except A0-A6 are used instead of just A6, as so: + +A13 A0 +---------------- +0 1xxx xBBB BBBB + +By using 6 bits, the maximum ROM size has been increased from 8K to 256K. + + +MC (Megacart) +----- + +This is the mapper for the "Chris Wilkson's Megacart". + +Only four addresses are used to bankswitch on this one. + +Up to 128K of ROM and 64K of RAM can be accessed. + +1000-13FF is selected by address 3C +1400-17FF is selected by address 3D +1800-1BFF is selected by address 3E +1C00-1FFF is selected by address 3F + +The value written determines what will be selected: + +00-7F written will select one of the 128 1K ROM banks +80-FF written will select one of the 128 512 byte RAM banks + +When a RAM bank is selected, the lower 512 bytes is the write port, while +the upper 512 bytes is the read port. + +On accessing address FFFC or FFFD, the last 1K bank points to the last bank in ROM, +to allow for system initialization. Jumping out of the last bank disables this. +It's debatable how easy this system would be to implement on a real system. + +Detecting when to disable the last bank fixing is difficult. The documentation +says: + +" + Megacart Specification, Rev1.1 + (c) 1997 Chris Wilkson + cwilkson@mit.edu + + Because the console's memory is randomized at powerup, there is no way to + predict the data initially contained in the "hot addresses". Therefore, + hardware will force slot 3 to always point to ROM block $FF immediately + after any read or write to the RESET vector at $FFFC-$FFFD. Block $FF + must contain code to initialize the 4 memory slots to point to the desired + physical memory blocks before any other code can be executed. After program + execution jumps out of the boot code, the hardware will release slot 3 and + it will function just like any other slot. +" + +Unfortunately, there's not an easy way to detect this. Just watching the address +bus won't work easily: Writing anywhere outside the bank 1C00-1FFF (i.e. bank +registers, RAM, TIA registers) will cause the switching to revert bank 3, crashing +the system. + +The only way I can see it working is to disregard any access to addresses 3C-3F. + +Emulators have it easier: they can simply watch the program counter, vs. the +address bus. An actual system doesn't have that luxury, unfortunately, so it must +disregard accesses to 3C-3F instead. + +EF (no name?) +----- + +This is a fairly simple method that allows for up to 64K of ROM, using 16 4K banks. +It works similar to F8, F6, etc. Only the addresses to perform the switch is +1FE0-1FEF. Accessing one of these will select the desired bank. 1FE0 = bank 0, +1FE1 = bank 1, etc. + +X07 (Atariage) +----- + +Apparently, this was only used on one cart: Stella's Stocking. +Similar to EF, there are 16 4K banks, for a total of up to 64K of ROM. + +The addresses to select banks is below the ROM area, however. + +The following TWO masks are used: + +A13 A0 +---------------- +0 1xxx nnnn 1101 + +This means the address 80B selects bank 0, 81B selects bank 1, etc. + +In addition to this, there is another way: + +A13 A0 +---------------- +0 0xxx 0nxx xxxx + +This is somewhat special purpose: Accessing here does nothing, unless one of the +last two banks are selected (banks 14 or 15). In that case, the new bank is: + +111n i.e. accessing 0000 will select bank 14 (Eh, 1110b) while accessing 0040 +will select bank 15 (Fh, 1111b). This allows for bankswitching by accessing +TIA registers at 00-3F or 40-7F without incurring any overhead. + + + +4A50 (no name) +----- + +Upon review, I don't think this method is terribly workable on real +hardware. There's so many problems that I kinda gave up trying to +count them all. Seems that this is more of a "pony" method than something +actually usable. ("pony" referring to "I want this, and that, and that, and +a pony too!") + +One major problem is that it specifies that memory can be read and written +to at the same address, but this is nearly impossible to detect on a 2600 +cartridge. You'd almost have to try and figure out what opcodes are being +run, and what cycle it's on somehow, all just by watching address and +data bus state. Not very practical. + +The other problem is just the sheer volume of things it is supposed to do. +There's just tons and tons of unnecessary things like attempting to detect +BIT instructions, handling page wraps and other silly things. + +This all supposidly fit into a Xilinx XC9536XL but I am not sure how the +chip could handle the RAM issue above at all. It almost needs to see R/W +and M2 (clock) to be able to properly do most of the things it's doing. + + +---------------------------------------------- + +Peripherals +----------- + + +Spectravideo Compumate Add-on +----- + +This is more than just a cartridge mapper- it's also a "computer" add-on. +There's two 8K EPROMs soldered on top of each other. There's two short +wires with DB-9's on them which you plug into the two controller ports. +A 42 or so key membrane keyboard with audio in and audio out, and 1K of RAM. + +Port A on the RIOT is used to run most of the functions on the Compumate: + +7 0 +--------- +ACRE 31BB + +A - Audio input from tape player +C - Audio out to tape player and 4017 CLK +R - 4017 RST, and RAM direction. (high = write, low = read) +E - RAM enable. 1 = disable RAM, 0 = enable RAM +3 - Row 3 of keyboard +1 - Row 1 of keyboard +B - 2 bit ROM bank number + +All bits are outputs except for the 2 row inputs from the keyboard. + +Unlike most things, the Compumate uses all three of the TIA inputs on each +joystick port (paddles and fire). + +TIA inputs: + +0 - function key +1 - pulled high thru 20K resistor +2 - pulled high thru 20K resistor +3 - shift key +4 - Row 0 +5 - Row 2 + + +Memory Map: +----------- + +1000-1FFF : selectable 4K ROM bank (selected by D0, D1 on portA) + +On powerup, the port is all 1's, so the last bank of ROM is enabled, RAM is +disabled. + +when RAM is enabled: + +1000-17FF : 2K of RAM. It's mapped into 1000-17FF. Unlike most 2600 carts, +bit 5 of portA controls if the RAM is readable or writable. When it's high, +the RAM is write only. When it's low, it is read only. There's no separate +read and write ports. + + +Keyboard: +--------- + +The keyboard's composed of a 4017 1 of 10 counter, driving the 10 columns of +the keyboard. It has 4 rows. The 4 row outputs are buffered by inverters. + +Bit 5 of portA controls the reset line on the 4017. Pulling it high will reset +scanning to column 0. Pulling it low will allow the counter to be clocked. + +Bit 6 of portA clocks the 4017. Each rising edge advances the column one +count. + +There's 10 columns labelled 0-9, and 4 rows, labelled 0-3. + + Column + + 0 1 2 3 4 5 6 7 8 9 ++---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +| 7 | | 6 | | 8 | | 2 | | 3 | | 0 | | 9 | | 5 | | 1 | | 4 | 0 ++---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ ++---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +| U | | Y | | I | | W | | E | | P | | O | | T | | Q | | R | 1 ++---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ Row ++---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +| J | | H | | K | | S | | D | |ent| | L | | G | | A | | F | 2 ++---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ ++---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +| M | | N | | < | | X | | C | |spc| | > | | B | | Z | | V | 3 ++---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ + +Function and Shift are separate keys that are read by 2 of the paddle inputs. +These two buttons pull the specific paddle input low when pressed. + +Because the inputs are inverted, a low indicates a pressed button, and a high +is an unpressed one. + +The audio input/output are designed to drive a tape player. The audio output is +buffered through an inverter and 2 resistors and a capacitor to reduce the level +to feed it into the tape player. + +The audio input is passed through a .1uf capacitor and is pulled to 1/2 supply +by two 20K resistors, then it goes through a hex inverting schmitt trigger to +square it up. This then runs into bit 7 of portA. + + +DPC (Pitfall 2) +----- + +Back in the day, this game was da shizzle (and IMO still is). It did its trick via +a custom chip in the cartridge. Fortunately for us, there's a patent that describes +lots of the internal workings of the chip (number 4644495, "video memory system"). + +Interestingly, the patent shows the DPC as a *separate* device. You plug a +passthrough cartridge into your 2600, then plug the game cartridge into the +passthrough. Apparently, Activision thought that people wouldn't like this, or +there was some other reasoning behind it and they ditched that idea and went with +the DPC inside the cartridge. + +Unfortunately for Activision, it was filed in January of 1984, during the height of +the crash. The inventor is listed as David Crane. + +OK, enough background. Now onto the meat: + +The DPC chip is just 24 pins, and needs to pass through the chip enable to the +game ROM on the cartridge, so it can only address 2K of memory. This means the +DPC shows up twice in the address space, once at 1000-107F and again at 1800-18FF. + +There's been some discussion about the pitch of the music generated by this chip, +and how different carts will play the music at different pitches. Turns out, on the +cart, the frequency is determined by a resistor (560K ohms) and a capacitor integrated +onto the die of the DPC chip itself. The resistor is a 5% tolerance part, and the +process variations of the DPC itself will control the frequency of the music produced +by it. + +If you touch the resistor on the cartridge board, the music pitch will drastically +change, almost like you were playing it on a theremin! Lowering the resistance makes +the music pitch increase, increasing the resistance makes the pitch lower. + +It's extremely high impedance so body effects of you touching the pin makes it +vary wildly. + +Thus, I say there's really no "one true" pitch for the music. The patent, however, +says that the frequency of this oscillator is 42KHz in the "preferred embodiment". +The patent says that it can range from 15KHz to 80KHz depending on the application +and the particular design of the sound generator. I chose 21KHz (half their preferred +value) and it sounds fairly close to my actual cartridge. + +Address map: + +Read Only: +1000-1003 : random number generator +1004-1005 : sound value (and MOVAMT value ANDed with draw line carry, with draw line add) +1006-1007 : sound value (and MOVAMT value ANDed with draw line carry, no draw line add) +1008-100F : returned data value for fetcher 0-7 +1010-1017 : returned data value for fetcher 0-7, masked +1018-101F : returned data value for fetcher 0-7, nybble swapped, masked +1020-1027 : returned data value for fetcher 0-7, byte reversed, masked +1028-102F : returned data value for fetcher 0-7, rotated right one bit, masked +1030-1037 : returned data value for fetcher 0-7, rotated left one bit, masked +1038-103F : fetcher 0-7 mask + +Write Only: +1040-1047 : fetcher 0-7 start count +1048-104F : fetcher 0-7 end count +1050-1057 : fetcher 0-7 pointer low +1058-105B : fetcher 0-3 pointer high +105C : fetcher 4 pointer high and draw line enable +105D-105F : fetcher 5-7 pointer high and music enable +1060-1067 : draw line movement value (MOVAMT) +1068-106F : not used +1070-1077 : random number generator reset +1078-107F : not used + +random number generator +----------------------- + +The random number generator is used on Pitfall 2 to make the eel flash between white and +black, and nothing else. Failure to emulate this will result in the eel not flashing. + +It's an 8 bit LFSR which can be reset to the all 0's condition by accessing 1070-1077. +Unlike a regular LFSR, this one uses three XOR gates and an inverter, so the illegal +condition is the all 1's condition. + +There's 255 states and the following code emulates it: + +LFSR = ((LFSR << 1) | (~(((LFSR >> 7) ^ (LFSR >> 5)) ^ ((LFSR >> 4) ^ (LFSR >> 3))) & 1)) & 0xff; + +Bits 3, 4, 5, and 7 are XOR'd together and inverted and fed back into bit 0 each time the +LFSR is clocked. + +The LFSR is clocked each time it is read. It wraps after it is read 255 times. (The +256th read returns the same value as the 1st). + +data fetchers +------------- + +Internal to the DPC is a 2K ROM containing the graphics and a few other bits and pieces +(playfield values I think) of data that can be read via the auto-incrementing data +fetchers. + +Each set of 8 addresses (1008-100F for example) return the data from one of the 8 +data fetcher pointers, returning the data in a slightly different format for each. +The format for the 6 possible register ranges is as follows: + +For the byte "ABCDEFGH" (bit 7 to bit 0) it is returned: + +1008-100F: ABCDEFGH (never masked) +1010-1017: ABCDEFGH +1018-101F: EFGHABCD (nybble swap) +1020-1027: HGFEDCBA (bit reversed) +1028-102F: 0ABCDEFG (shifted right) +1030-1037: BCDEFGH0 (shifted left) + +Reading from each set of locations above returns the byte of data from the DPC's +internal ROM. Reading from 1008 accesses data at DF (data fetcher) 0's pointer, +then decrements the pointer. Reading from 1009 accesses data at DF1, and so on. + +There is no difference except how the data is returned when reading from 1008, +1010, 1018, 1020, etc. All of them return data pointed to by DF0's pointer. Only +the order of the bits returned changes. + +I am not sure what purpose returning the data shifted left or right 1 bit serves, +and it was not used on Pitfall 2, but that's what it does. I guess you could +use it to make a sprite appear to "wiggle" left and right a bit, if it were 6 pixels +wide. + +All of these read ports returns the data masked by an enable signal, except for +1008-100F. The data here is never masked. (more about this in a minute) + +To read data out of the chip, first you program in its start address into the +pointer registers. These are at 1050-1057 for the lower 8 bits of the pointer +value, and 1058-105F for the upper 4 bits of the pointer value. This forms the +12 bit address which can then be used to index the DPC's ROM. + +A few of the upper bits on 105C-105F are used for a few other purposes, which will be +described later. + +Masking the data: +----------------- + +1038-103F is the readback for the mask value +1040-1047 is the start count +1048-104F is the end count + + +The mask value can be read via 1038-103F. It returns 0 when graphics are masked, and +FFh when they are not masked. (0 = reset, 1 = set) + +The basic synopsis is thus: + +When the lower 8 bits of the pointer equals the start count, the mask register is set. +When the lower 8 bits of the pointer equals the end count, the mask register is reset. +Writing to the start count register also sets the register. + +This allows one to have the sprites only show up on specific scanlines, by programming +the proper start and end counts, and the proper starting value into the pointer. This +way, the sprite can be drawn from top to bottom of the screen, and have it only appear +where it is desired without having to do anything else in the 2600 code. + +Making Music: +------------- + +The music is generated by repurposing three of the fetchers, the last three. +Each fetcher can be individually selected for music or fetching. + + 7 0 + --------- +105D-105F: xxSM PPPP + +S: Select clock input to fetching counter. 0 = read pulse when the proper returned +data register is read (i.e. for fetcher 5, 1015 is being read) 1 = music oscillator. + +M: Music mode. 1 = enable music mode, 0 = disable music mode. + +P: upper 4 bits of the 12 bit data fetcher pointer. + + +I am not sure why you can separately select the clock source and the music mode, +but you can. Maybe they had some plans for externally clocking the chip via some +logic to bump the pointers. + +Normally you set both the M and P bits to make music. + +When in music mode, the lower 8 bits of the fetcher pointer is used as an 8 bit down +counter. Each time the lower 8 bits equals FFh, it is reloaded from the start count +register. + +To turn the data fetcher into a square wave generator takes very little hardware. The +start/end count registers are used as-is to toggle the flag register. + +This means that the duty cycle of the square waves produced can be varied by adjusting +the end count register relative to the start count register. I suspect the game simply +right shifts the start count by one and stuffs it into the end count to produce a +50% duty cycle waveform. + +The three flag outputs for fetchers 5 to 7 are fed into a cool little circuit composed +of a 3 to 8 decoder and four 4 input NAND gates to produce the 4 bit audio output. + +The output is as follows: + + fetcher result + 567 +--------------------- + 000 0h + 001 4h + 010 5h + 011 9h + 100 6h + 101 Ah + 110 Bh + 111 Fh + + +This is a somewhat nonlinear mixing of the three channels, so the apparent volume of them +is different relative to each other. + +The final 4 bit output value from the above table is then available to read at address +1004-1007, in bits 0 to 3. + +Pitfall 2 just reads this location and stuffs it into the audio register every scanline or +so. The value read at 1004-1007 is the instantanious value generated by the fetchers and +mixing hardware. + + +HMOVE adjustment stuff: +----------------------- + +I have not done much research on how this works, and P2 doesn't use it. It appears to +let you draw curved lines using a missile or two, probably to make swinging vines. + +The patent explains how it works, but it just appears to be an adder that adds the start +count value to itself via a multiplexer and stuff. It appears to let you input an +offset and it calculates a new hmove value. Not sure how useful this really is. + + +AR (Starpath Supercharger) +-------------------------- + +Aaah the good ol' Supercharger. This is the large "cartridge" that you could plug into +your 2600 that had 6K of RAM which you could download games into off of cassette tape. + +The idea being you plug your cassette player into the cable coming off of the cartridge, +and then you can download games into RAM from it. + +When first turned on, it says "rewind tape" and "press play". When this is done, it will +start loading the game off tape and fill the screen in with blue bars from the sides +to the inside while a rising tone plays. When the screen is fully blue, it then clears +the screen and says "stop tape", and then the game starts. + +If there is an error (corrupt tape, etc) it will continously flash "rewind tape" on +the screen until the audio input stops toggling. + +Games can re-enable the BIOS ROM and load more data off tape at any time. + +So, that's what it is... but how does it work? + +I didn't find a whole huge amount of information on how the Supercharger actually +WORKS. There was some info about how to program it, but nothing on how the +ASIC in the Supercharger does its thing. + +Well, turns out it's pretty cool and as far as I know, unique. + +First off, there are two registers on the Supercharger. The first is the audio +input register. It's at FFF9: + + 7 0 + --------- +FFF9: 0000 000A + +A: Supercharger audio data. 0 = low input, 1 = high input. + +The audio input's just a filtered and schmitt triggered version of the audio data +coming into the Supercharger. The upper 7 bits must all be 0's, or else it +will not properly read the data. For testing, I fed my FPGA 2600's Supercharger +with data from Bankzilla's tape emulator. This is simply a digital output that +is fed into the Supercharger's audio pin (and to my FPGA board). + +The next register is the control register. + + 7 0 + --------- +FFF8: DDDB BBWE + +D: write delay (see below) +B: bankswitching mode (see below) +W: RAM write enable (1 = enabled, 0 = disabled) +E: ROM power enable (0 = enabled, 1 = turn off ROM) + +To write to RAM or the control register on the Supercharger requires a somewhat +round-about method. First, you read a location at F000-F0FF, then you read +either FFF8 to write to the control register, or somewhere else in RAM. +Sooo, to write to the control register, the following type of code is +used: + +;A = value we will write to the banking register +TAX +LDA F000,X +LDA FFF8 + +The TAX moves the value we wish to write into F000,X (i.e. if we wish to write 16h +to the control register, the location F016 is read). + +Next, we read FFF8 which performs the write. *any* instruction that reads FFF8 +will suffice. The BIOS uses BIT FFF8 and LDX FFF8 sometimes, depending on +what's convenient, and what flags or registers need to be saved. The +instruction really does not matter, so long as it simply READS. + +Note: THERE IS NO UPPER LIMIT on the number of cycles that can elapse between +reading F0xx and reading FFF8 to write to the control register. Usually, +it is written to immediately after reading F0xx, but not always. The very +last write to FFF8 which sets the RAM banking before launching the game +after loading waits a very long time before reading FFF8 to set the banking +mode. + +The basic method it does the final write is as such: + +LDA F000,X + + +FA0B : 9A TXS ;X entered at ffh +FA0C : A2 3 LDX #$3 +FA0E : BC AB FD LDY $FDAB,X +FA11 : 94 FA STY $FA,X ;load cmp fff8h, jmp opcode only +FA13 : CA DEX +FA14 : 10 F8 BPL $FA0E ;jmp target was at fe/ff +FA16 : A0 0 LDY #$0 +FA18 : 84 81 STY $81 +FA1A : 4C FA 0 JMP $FA ;run the code we loaded in RAM + +00FA : CD F8 FF CMP $FFF8 ;sets up control register for the game +00FD : 4C xx xx JMP xxxx ;we now jump to the start of our code + + +FDAB : CD F8 FF 4C ;this is the code loaded into RAM + + +The control register contains a few different things. + +The ROM power can be turned on and off (which IMO is dumb. The ROM doesn't +draw appriciable power, but they have a PNP transistor that can turn it on +and off anyways. Most games turn it off when they are done loading, and +then turn it back on if they need to load again from tape. I guess they +were worried it was going to vampire too much current from the system, so +running it only as long as necessary was their solution. + +The next bit is the write enable. If set, the RAM can be written to. +If clear, it is read-only. This is useful for loading 2K and 4K games into +the Supercharger to play them. Not much use otherwise. The Supercharger +will never attempt to write to ROM, and it will not write to RAM if this +bit is clear. + +Banking mode. The Supercharger allows for 8 different memory maps, depending +on how these three bits are set. The following are supported: + +BBB 1000-17FF, 1800-1FFF +--- --------------------- +000 - RAM bank 3 ROM +001 - RAM bank 1 ROM +010 - RAM bank 3 RAM bank 1 +011 - RAM bank 1 RAM bank 3 +100 - RAM bank 3 ROM +101 - RAM bank 2 ROM +110 - RAM bank 3 RAM bank 2 +111 - RAM bank 2 RAM bank 3 + +ROM can never be mapped into 1000-17FF but this makes sense, since the code is +written to only run from 1800-1FFF. Also, a few combinations are not possible +such as RAM bank 1, RAM bank 2, and RAM bank 2, RAM bank 1. All others are +possible. + +The last part of the control register is the write pulse delay. I don't think +anything uses this and just keeps it at 0. Heck, it may not even be implemented. + +So that takes care of how to read audio and how to access the control register. +That leaves writing to RAM. + +The Supercharger watches all 13 address lines to determine when RAM should be +written. It first watches for a write to F0xx, just like when writing to the +control register, then it waits 5 address bus transitions, then it attempts to +write data to the RAM chip by pushing the value onto the data bus, while the CPU +is reading. + +The usual way this is done in the BIOS is like so: + +;X = byte to write +LDA F000,X ;tell the supercharger what to write +LDA (8B),Y ;write it! + +If we look at bus transitions, it looks like this: + +Assume that the code is sitting at 1800, and 8B/8C holds the address 1100h. +Also assume X = 66h + +c# address, data +1: 1800 BD ;LDA,X opcode +2: 1801 00 ;low byte of add +3: 1802 10 ;hi byte of add +4: 1066 ?? ;read address 1066 (this is the RAM byte, could hold anything). +5: 1803 B1 ;LDA (),y opcode +6: 1804 8B ;zeropage address of pointer +7: 008B 00 ;low byte of destination +8: 008C 11 ;hi byte of destination +9: 1100 66 ;Supercharger writes data now to RAM by forcing value on bus + +As we can see, cycle 9 is exactly 5 cycles after cycle 4, where we read from F0xx. +The supercharger will only attempt to write if writes are enabled, and the area +we're attempting to write to is set up for RAM. It will not attempt to write to +ROM, or outside the range of 1000-1FFF. + +This method of operation has an interesting side effect. Because the Supercharger +forces a value onto the bus while the CPU is reading, the CPU will actually +READ this value! This makes sense- the CPU doesn't know if it's reading RAM, ROM, +or the Supercharger's write value. + +In fact, this is REQUIRED for it to even work. It does some pretty extensive +RAM tests on powerup, and if it cannot write to RAM it will flash the screen +yellowish/black as it attempts to test RAM over and over. If RAM fails to test +properly, it will reset and start again. + +The RAM testing code looks like this: + +FF58 : A9 F1 LDA #$F1 +FF5A : 85 8C STA $8C +FF5C : A0 0 LDY #$0 ;start address = F100 +FF5E : 84 8B STY $8B +FF60 : AD 0 F0 LDA $F000 ;write 00h +FF63 : B1 8B LDA ($8B),Y ;write ! +FF65 : D1 8B CMP ($8B),Y ;is it 00h? +FF67 : D0 14 BNE $FF7D ;no +FF69 : AD FF F0 LDA $F0FF ;write ffh +FF6C : B1 8B LDA ($8B),Y ;write ! +FF6E : D1 8B CMP ($8B),Y ;is if ffh? +FF70 : D0 B BNE $FF7D ;nope +FF72 : C8 INY +FF73 : D0 EB BNE $FF60 ;last byte of page? +FF75 : E6 8C INC $8C +FF77 : A5 8C LDA $8C +FF79 : C9 F8 CMP #$F8 +FF7B : D0 E3 BNE $FF60 ;last page? +FF7D : 60 RTS ;return zero set if passed + +Basically what happens is this: It first sets up the address F100 (aka 1100) into +8B/8C, then it steps through the entire RAM area up to 17FF, and returns with +Z flag set, if it passed, or NZ if it fails. + +The code at FF60-FF66 is very interesting: It first reads from F000 so that +we will write 00 to memory. Then it writes it and immediately compares it. +Remember that the CPU will READ what the Supercharger writes, so the accumulator +will hold 00 after executing that LDA (),y! + +The same test is repeated, this time by writing FF. If it can step through all +locations without erroring out, it passes the test. This code only tests one +2K bank (minus the first 256 locations, more on that in a minute). The code is +then called three times, testing each bank of RAM in turn. + +This testing brings up an interesting note about the Supercharger's RAM. + +When writes are enabled to RAM, you CANNOT READ FROM 10xx WITHOUT CORRUPTING RAM. +This means, you cannot read data here, and you cannot excute code here! Doing +so will trigger writes, which will overwrite whatever happens to be 5 cycles later +if it's in RAM! You *CAN* write to 1000-10FF, however just fine... you just +cannot read it or execute from it without first disabling writes. In fact, the +BIOS starts writing at 1000 when it's loading the game from tape. Since it never +attempts to execute code from there or read back the data, this is legal. + +The BIOS' RAM testing routine must therefore skip testing the first 256 bytes +of each bank. It *could* test it, but I guess they figured running the code from +RAM to do it would've been too much of a hassle, concidering space was at +a premium. + +Remember how I said the Supercharger counted *BUS TRANSITIONS* to know when to +write to RAM? Well, this is very very important. You cannot just count CPU cycles. +That won't work (because the Supercharger cannot see the CPU's clock line for one). + +Here's the other way that you can write to RAM: + +FFC7 : A0 8 LDY #$8 +FFC9 : D9 0 F0 CMP $F000,Y +FFCC : EA NOP +FFCD : CD E3 F7 CMP $F7E3 + +This writes 8 to location 17E3. Notice the NOP to "fill up" the cycles. If we +look at what the address/data bus is doing, we will see how this can work, even +though the write occurs 6 cycles after the CMP, instead of 5. + + +c# address, data +1: FFC9 D9 ;CMP,Y opcode +2: FFCA 00 ;low byte of add +3: FFCB F0 ;hi byte of add +4: F008 xx ;read RAM here, contents unimportant +5: FFCC EA ;NOP opcode +6: FFCD CD ;CMP opcode, but throw it away (NOP is 2 cycles) +7: FFCD CD ;CMP opcode +8: FFCE E3 ;low byte of add +9: FFCF F7 ;hi byte of add +10:F7E3 08 ;write to F7E3 + +Yes, it does indeed take 6 cycles to get to the write... however, look at the address +bus. There's only FIVE transitions! The byte at FFCD gets read twice. This is +because NOP is a 2 cycle instruction. NOP's second cycle reads the next opcode +and throws it away, and does NOT increment the program counter. So, the next +cycle reads it too and fetches CD for the CMP opcode. Pretty tricky stuff! + +Note that when I say "transition", I am talking about when one or more of the 13 +address lines changes. The Supercharger can only count cycles by watching these +address lines. That's why it only counts up 5 transitions on the above code snippet. +The double access to FFCD counts as 1 transition as far as the Supercharger is +concerned. + +That about wraps up the Supercharger's hardware. + + +Supercharger Tape Format +------------------------ + +The tape format on the Supercharger is fairly straight forward. It's a form of +pulse width modulation. Interestingly, the length of the pulses is not fixed, and +the software on the Supercharger can adapt to a pretty wide range. + +According to the "tapedocs.txt" file: + + + "0" pulse "1" pulse +------------------------------- +minimum 158uS 317uS +optimal* 227uS 340uS +maximum 317uS 2450uS + +* According to the tapedocs.txt file, the filters on the Supercharger are tuned +specifically for 227uS and 340uS pulse lengths. + + +NOTE: these times are for the entire pulse, i.e. the low and high portions of it. +The low and high portions would thus be half these values. + + +i.e. if the pulse is 300uS long... + + low high + +____________------------ + + \--150uS--/ \--150uS--/ + + +Here is a generic representation of what a typical signal looks like: + +____----____----____----________--------________--------____----________-------- + + \--0--/ \--0--/ \--0--/ \------1------/ \------1------/ \--0--/ \------1------/ + + +The "one" pulses only have to be approximately 90uS wider than the "zero" pulses, +but it's a good idea to have them at least 25% wider so the Supercharger can +adapt to tape speed fluctuations during the load. + + +A Supercharger tape load is composed of 6 separate parts: + +--------------------------------- +1. Preamble + +The preamble is a 50% duty cycle low frequency waveform that causes all the +elements in the tape chain (amplifiers, the filter in the Supercharger proper, +etc) to stabilize. Without this preamble, the volume level into the 'charger +can change while the capacitors in the signal chain charge. + +A frequency of around 750Hz (666uS low, 666uS high) is pretty decent. + +The preamble needs to be at least 800 pulses long (i.e. around 1 second or more). + +--------------------------------- +2. Synchronization + +After the preamble, at least 256 or more bytes of 55h (0/1/0/1) bits need to be +sent at the chosen bit rate. The Supercharger software uses this to synchronize +its decoder software. + +--------------------------------- +3. Start pulse + +To tell the Supercharger our data is coming, a final 0 pulse is sent. After this +point, the Supercharger header follows. + +--------------------------------- +4. Header data + +0: WORD Start address +2: BYTE Control word +3: BYTE Block count +4: BYTE Header checksum +5: BYTE Multiload number +6: WORD Progress bar speed + +All values are little endian. Bytes are sent out, MSB first (i.e. left shift +the data byte). + +Start address: The start address specifies where the 6502 will +jump to after all the data is loaded from the tape. + +Control word: Specifies the value to load into the Supercharger's control register. +Usually the upper 3 bits should be clear. (See above for more info on the control +register in the Supercharger section). + +Block count: How many 256 byte blocks will be sent in this transfer. + +Header checksum: As the name indicates, a checksum of the header. The checksum +is computed by starting out with 55h and subtracting every byte in the header +(not including the sumcheck byte itself). + +The result is that when the Supercharger adds up ALL bytes of the header (including +the sumcheck byte) it will be 55h. All carries/borrows are ignored when calculating +the sumchecks. + +This is what the demo unit's header contains: + + .dw 0ffc0h ;start address of code + .db 01bh ;control word: 1000-17ff= b.3, 1800-1fff= b.2 ROM=off WR=on + .db 001h ;# of 256 byte blocks + .db 06dh ;header checksum + .db 000h ;this is not a multiload + .dw 0010ch ;speed for progress bars + +when all these bytes (c0, ff, 1b, 01, 6d, 00, 0c, 01) are added together, the result +is 255h... dropping carries (AND with ffh) results in 55h... meaning that the +sumcheck passes and the data was properly received. + +Multiload number: If the game has no multiload, this byte is simply kept at 0. If +this game IS a multiload game, then the sequence number is stored here. This lets +Supercharger BIOS know if the proper game load is being received or not. + +The first load of a multiload game is always 0. When the first load wishes to +load the second (or subsequent) part(s), the current load tells the Supercharger +BIOS which load it is looking for and runs the BIOS' receive routine again. + +If the data received is not the proper load #, it will do a "false load" and load +the data, but then throw the results away and wait for the next load to come around. +This is repeated until the correct load number is reached and loaded. + +On Escape from the Mindmaster this can be seen if you lose all your lives in the first +load. It will instruct you to press "play" on your tape player, and will load part 2. +But the ending is not in part 2, so it throws the data away after loading it and +proceeds to load part 3, which is thrown away, and then the final part is loaded. + +To prevent someone from getting cute, the multiload sequence numbers were never +recycled. They were allocated like so: + +Escape from the mindmaster uses 1, 2, and 3 +Dragonstomper uses 4 and 5 +Survival Island uses 6 and 7 + +Progress bar speed: The value here specifies how fast the progress bars.. well.. +progress as the game is loaded. If the value is wrong the bars will proceed to the +middle before the game is fully loaded. + +The value is calculated by taking the block count and multiplying it by +approximately 22.8 i.e. for a game that's 6K in size (each block being 256 bytes) +is 24 blocks * 22.8, which is 547 (223h). + +This works for most bank sizes, however when only 1 bank is loaded, the value +has to be 10ch for some reason I have not researched. + +--------------------------------- +5. Data blocks + +Once the header is finished sending, the data is sent in 256 byte blocks. Each +block has a 2 byte header, followed by the 256 bytes of data. + +Block header: + +0: BYTE Block location +1: BYTE Checksum + + +Block location: This is the block location in RAM where the data will be loaded. +Blocks are specified in the following format: + +7 0 +--------- +000B BBRR + +B: block number, from 0 to 7 +R: RAM chip # + +Ram chip number is specified like so (reffing the bank numbers in the Supercharger +documentation above) + +00 - RAM bank 1 +01 - RAM bank 2 +10 - RAM bank 3 +11 - invalid (would select ROM) + +The block number is the particular 256 byte block in the specified RAM bank. + +So, to load data sequentially, from RAM bank 1's first block, to RAM bank 3's +last block, the following block locations would be used: + +RAM 1: 00, 04, 08, 0C, 10, 14, 18, 1C +RAM 2: 01, 05, 09, 0D, 11, 15, 19, 1D +RAM 3: 02, 06, 0A, 0E, 12, 16, 1A, 1E + +Checksum: The checksum for the block is calculated exactly like the header's +checksum is. All 258 bytes (256 data bytes, block location byte, and sumcheck) +are added together, and the result must be 55h. If the sumcheck fails, the +"rewind tape" message flashes as long as audio data is coming in, then when the +audio data stops coming in, it reverts to the "press play" message. + +--------------------------------- +6. Postamble + +After all the blocks of data are sent, the Supercharger will play the "Press stop" +message until audio data stops coming in, and then it starts running the game. + +The postamble is used to detect when stop is pressed. The postamble is simply +a string of "0" bits. The length of the postamble should be at least 256 bits, +but it can be as long as desired. The Supercharger will not run the game +until the postamble stops, however. + +--- + + +Supercharger Demo Unit +---------------------- + +This doodad is pretty cool. First, you plug a Supercharger into your 2600. Then +you plug the audio cable from it into this black box. Then the black box plugs +into the joystick port. + +You can optionally plug a regular joystick into the other joystick port. + +The demo unit itself is a nondescript black box with a label on it. Inside the box is +quite a bit of hardware. + +* 8 2764 EPROMs +* 1 2732 EPROM +* 1 6805E CPU +* various discrete logic + +The basics of operation are as such: + +When powered up, a small bootloader is loaded into the Supercharger through its +audio cable. Once this initial bootloader is loaded, the audio cable is never used +again until the system is reset or power cycled. + +After the bootloader is sent, the rest of the data to the Supercharger's RAM is loaded +through the joystick port 4 bits at a time. + +The net result is incredibly high loading speeds. A complete 6K of RAM data can be +sent in around 250ms. + +Internally, there is a 6805E CPU made by Motorola. This is similar to the 68705 and other +microcontrollers Motorola made, except it's the external ROM version. There is no +ROM on the chip. + +The two IO ports are connected as such: + +PortA: This port is used to send data out 8 bits at a time to the 2600 through the joystick +port. The byte of data is simply written here, and the 2600 picks it off when it's good +and ready (there's an explaination later on of how this works exactly). + +PortB: + +7 0 +--------- +AExB BBBB + +A: Audio output. This port pin connects to the Supercharger's audio cable through a resistor +divider that cuts the audio level down to a level of a few hundred millivolts to prevent +overloading the audio input. + +E: EPROM enable. Must be low to enable the 8 2764 EPROMs. +B: EPROM bank. Selects a 2K EPROM bank from the 2764's (more about this later) + + +PortA's data is passed through a quad 2:1 multiplexer (a 74LS157). The select line connects +to bit 3 of the joystick port. When it's low, the multiplexer outputs the lower nybble of +the byte on PortA. When it's high, it outputs the upper nybble. + +The data bits from the muxer connect like so: + +bit 3: this is acting as an output- it runs the select line of the 74LS157, and also +connects to /IRQ on the CPU. +bits 2 to 0 connect to the multiplexer's upper 3 bits. + +The fire button input connects to the multiplexer's lowest bit. + +So, to read a byte of data in through the controller port, the select line is pulled low +via the RIOT register at 280h. Bit 3 must be set as an output, while bits 0-2 are inputs. + +bits 3,2, and 1 of the data byte are read on 280 bits 2 to 0. bit 0 of the data byte is +read via 3Dh bit 7. + +the select line is thin pulled high via 280.3 + +bits 7,6, and 5 are then read from 280 bits 2 to 0 . bit 4 of the data byte is read via +3Dh bit 7. + +There's a very elegant piece of code that does this on the bootloader, which gets loaded +into RAM: + +;enters with Y = 3fh +0081 : CD 0 F0 CMP $F000 ;select proper RAM bank (note: self modifying) +0084 : CD F8 FF CMP $FFF8 +0087 : A9 7F LDA #$7F +0089 : C5 3D CMP $3D ;puts fire button data into carry and invert it +008B : 4D 80 2 EOR $280 ;get data, and invert it (data is sent inverted) +008E : 8D 80 2 STA $280 ;write inverted data back (toggles bit 3 to demo unit) +0091 : 2A ROL +0092 : A ASL +0093 : A ASL +0094 : A ASL ;put lower 3 bits into bits 6 to 4, carry into 3 +0095 : 85 B7 STA $B7 ;save for now +0097 : A9 7F LDA #$7F +0099 : C5 3D CMP $3D ;put fire button into carry and invert it +009B : 4D 80 2 EOR $280 ;get data, and invert it +009E : 8D 80 2 STA $280 ;write inverted data back +00A1 : 29 7 AND #$7 ;strip off upper bits +00A3 : 5 B7 ORA $B7 ;or it on to add into bits 2 to 0 +00A5 : 2A ROL ;finish up by putting carry into 0 and shifting the mess left +00A6 : AA TAX +00A7 : DD 0 F0 CMP $F000,X ;write it to supercharger RAM +00AA : D1 B9 CMP ($B9),Y +00AC : 88 DEY +00AD : 10 D8 BPL $FF8A ;do all bytes +00AF : CD 19 F0 CMP $F019 ;bankswitch +00B2 : CD F8 FF CMP $FFF8 +00B5 : 60 RTS + + +This core routine is used to load data. It lives in the FF00-FFBF range and is loaded +into RIOT RAM when data needs to be transferred. + +Since bit 3 of 280h is also connected to the /IRQ line on the CPU, this is used to +tell the 6805 when a byte of data has been read, and it should get the next one ready +to go. + +That's about it for the 2600 to demo unit interface. + +The memory map of the demo unit is extremely simple: + +0000-0FFF : on-chip resources (ports, the timer, RAM) +1000-17FF : 2K bank of data from the 64K worth of 2764's +1800-1FFF : 2K of BIOS code from the 2732 EPROM. + +The 2K bank of data at 1000-17FF comes from the 64K of EPROMs. PortB bits 0-4 select +a desired 2K bank. + +That's about it for the details. There are a few other amusing (to me) details of the +hardware, however. + +When the unit starts, there's a 10 second countdown. This is there for a reason. +Those 8 2764's can draw a lot of power if they were all turned on at once, so to +enable the EPROMs there are 8 PNP transistors connected to a decoder, which connect +to the VCC lines of each EPROM. So, when you wish to read from the EPROMs, you must +actually enable the power line to it via a decoder chip (74LS42). + +To prevent a huge power suck from the 2600, there's a large capacitor that supplies +power to the EPROMs. I can't remember how big it was, but I think it was 4700uF. +This is connected through a resistor to 5V. So, that 10 second countdown at the +start is so this capacitor can charge. The countdown code and bootstraps are stored +in the 2K EPROM. + +Only one of the 8K EPROMs may be enabled at any time, and they can all be disabled +to prevent them drawing any power by clearing bit 6 of portB. The desired EPROM is +selected via bits 2,3,4 of portB. (bits 0 and 1 of portB connect to A11 and A12 +of the 8 EPROMs.) + +The 74LS42 is a 1 of 10 decoder, and the inputs are connected as such: + +7 0 +--------- +xDxC BAxx + +ABCD: the 4 selector inputs (A = LSB, D = MSB). x = not used. + +Thus, to enable an EPROM, bit 6 must be clear. When this bit is set, no outputs +connected to EPROM power enable transistors will be turned on. + +I am not 100% sure of the speed the demo unit's CPU runs at. It was 12 years ago, +but I think it was 4.1952MHz. I am using this on my demo unit FPGA emulation and +it works good. + +That about wraps up this mysterious piece of hardware. +