# ------------------------------------------------------------------- # CARTRIDGE/SERVER (c) Copyright 1996 Nat! & KKP # ------------------------------------------------------------------- # These are some of the results/guesses that Klaus and Nat! found # out about the Jaguar with a few helpful hints by other people, # who'd prefer to remain anonymous. Thanks go to marz@haari.mayn.de # for the pinout info. # # Since we are not under NDA or anything from Atari we feel free to # give this to you for educational purposes only. # # Please note, that this is not official documentation from Atari # or derived work thereof (both of us have never seen the Atari docs) # and Atari isn't connected with this in any way. # # Please use this informationphile as a starting point for your own # exploration and not as a reference. If you find anything inaccurate, # missing, needing more explanation etc. by all means please write # to us: # nat@zumdick.ruhr.de # or # kp@eegholm.dk # # If you could do us a small favor, don't use this information for # those lame flamewars on r.g.v.a or the mailing list. # # HTML soon ? # ------------------------------------------------------------------- # $Id: cartridge.html,v 1.19 1997/11/16 18:14:39 nat Exp $ # -------------------------------------------------------------------
Here's how to access the cartridge and its EEPROM as well as the Jaguar Server Cartridge. Actually when we say cartridge we mean the cartridge connector of the jag. Note that to access the memory mapped cartridge, you seem to need to do 32 bit accesses.
Jaguar Server ============= This is the protocol found on the BOOT ROM of your jaguar server "cartridge". The protocol used in the current JAGOS.BIN is a bit more extensive (noted with *) Its a kind of handshaking protocol that looks like this (and starts with reset): reset(): ~~~~~~~ Server: sends garbage (except $FF) Jaguar: ignores garbage Server: $FF Jaguar: 'O' 'K' Jaguar: next_command() next_command(): ~~~~~~~~~~~~~~~ Server: sends garbage (except $0-$7) Jaguar: ignores garbage Server: A number from 0 to 7 (11) MSB LSB (16 bit!!) Jaguar: 0: send_ok_to_host 1: copy_to_host 2: copy_from_host 3: copy_from_host_and_go 4: send_version_to_host 5: reset 6: test_FF 7: jsr_to 8: send_rom_type_to_host (*) 9: clear_memory (*) 10: nop (*) 11: send_eeprom_to_host (*) send_ok_to_host() ~~~~~~~~~~~~~~~~~ Jaguar: 'O' 'K' Jaguar: next_command() copy_to_host() ~~~~~~~~~~~~~~ Server: address MSB NSB ISB LSB Server: length MSB NSB ISB LSB Jaguar: sends [length] bytes from [address] Jaguar: next_command() copy_from_host(): ~~~~~~~~~~~~~~~~ Server: address MSB NSB ISB LSB Server: length MSB NSB ISB LSB Jaguar: receives [length] bytes into [address] Jaguar: next_command() copy_from_host_and_go() ~~~~~~~~~~~~~~~~~~~~~~~ Server: address MSB NSB ISB LSB Server: length MSB NSB ISB LSB Server: run-address MSB NSB ISB LSB Jaguar: receives [length] bytes into [address] Jaguar: (*run-address)() ;; JSR Jaguar: next_command() send_version_to_host() ~~~~~~~~~~~~~~~~~~~~~~ Jaguar: version number MSB NSB ISB LSB ;; ASCII Jaguar: next_command() will be 'B001' or somesuch for the BOOT ROM, will be '1.08' or somesuch for the downloaded JAGOS.BIN test_FF(): ~~~~~~~~~ Server: sends garbage (except $FF) Jaguar: sends garbage back Server: $FF Jaguar: next_command() jsr_to(): ~~~~~~~~ Server: run-address MSB NSB ISB LSB Jaguar: (*run-address)() ;; JSR Jaguar: next_command() send_rom_type_to_host() ~~~~~~~~~~~~~~~~~~~~~~~ Jaguar: either 'E' 'R' or 'D' 'R' ; ER means Server EPROM Jaguar: next_command() clear_memory() ~~~~~~~~~~~~~~ Server: start-address MSB NSB ISB LSB Server: end-address (exclusive) MSB NSB ISB LSB Jaguar: clears [length] bytes from [address] Jaguar: 'C' 'O' Jaguar: next_command() send_eeprom_to_host(): ~~~~~~~~~~~~~ Server: dummy word Jaguar: reads EEPROM Jaguar: send $0000 on success, $0001 on failure (MSB LSB) Jaguar: on success sends also 128 bytes of EEPROM data Jaguar: next_command() nop(): ~~~~~ Jaguar: next_command() SERVER INTERFACE : ================== R: SERVSTAT ($E1FD00) ~~~~~~~~~~~~~~~~~~~~~ 8 4 0 +--------^----+----+ | unused | st | +-------------+----+ 1..0 status (st): bit 0: read possible (1: yes 0:no) bit 1: write possible (1: no 0:yes) R: SERVREAD ($E1FE00) ~~~~~~~~~~~~~~~~~~~~~ 8 4 0 +--------^---------+ | byte | +------------------+ byte: get the next byte in the stream e.g. read_byte: .wait: BTST #0,SERVSTAT BEQ.B .wait MOVE.B SERVREAD,D0 R: SERVWRITE ($E1FF00-$E1FFFF) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 4 0 +--------^---------+ | byte | +------------------+ byte: write a byte into the steam, by reading from the address, whose lower 8 bytes matches your data byte. e.g. write_byte: MOVEA.L #SERVWRITE,A0 .wait: BTST #1,SERVSTAT BNE.B .wait MOVE.B 0(A0,D0.W),D0 Cartridge =-=-=-=-= This is the pinout of the cartridge: Pin ROW A ROW B -------------------------------------------------------------- 1 A10 ................... GND A9 GND A11 A23 A8 A22 5 A12 ................... A21 A7 A20 A13 A19 A6 GND A14 n.c.? 10 A5 ................... GND A15 n.c.? A4 GND N/A N/A N/A N/A 15 A16 ................... CPU Pin x A3 CPU Pin x A17 68000 HALT A2 CPU Pin 53 A18 RAM U23 Pin 12 20 CPU CE (U1..U4) Pin 57 .. RAM U24 Pin 12 GND 68000 R/W D15 CPU OE(LowWORD) D0 CPU OE(HighWORD) D7 GND 25 D8 ................... DSP Pin ? D14 DSP Pin ? D1 +10V (DIRECT) D6 n.c. D9 GND 30 D13 ................... n.c. D2 DSP Pin ? D5 GND D10 68000 RESET D12 CARD INSERT A 35 D3 ................... CARD INSERT B D4 VCC D11 VCC VCC ? D31 n.c. 40 D16 ................... EEPROM SERIAL DATA/STATUS D23 n.c. D24 EEPROM CLOCK D30 EEPROM SELECT D17 DSP Pin ? 45 D22 ................... *DSP Pin ? D25 DSP Pin ? D29 DSP Pin ? D18 DSP Pin ? D21 DSP Pin ? 50 D26 ................... DSP Pin ? D28 GND D19 68000 CLOCK 13.295453MHz D20 GND 54 D27 ................... GND And here is the pinout of the 42-leg ROM IC. ----u---- A18 1=| |=42 VCC? A17 2=| |=41 A 8 A 7 3=| |=40 A 9 A 6 4=| |=39 A10 A 5 5=| |=38 A11 A 4 6=| |=37 A12 A 3 7=| |=36 A13 A 2 8=| |=35 A14 A 1 9=| |=34 A15 A 0 10=| |=33 A16 !CE 11=| |=32 !BYTE GND 12=| |=31 GND !OE 13=| |=30 D15 D 0 14=| |=29 D 7 D 8 15=| |=28 D14 D 1 16=| |=27 D 6 D 9 17=| |=26 D13 D 2 18=| |=25 D 5 D10 19=| |=24 D12 D 3 20=| |=23 D 4 D11 21=| |=22 VCC --------- EEPROM: ~~~~~~~ The chip in the cartridge, that is used to save highscores or small amounts of save game data is a National Semiconductor NM93C14 compatible chip. This EEPROM has 128 bytes, which is organized as 64 16 bit words. Each cell is addressed by a number from $0 to $3F. The chip can be accessed with a maximum speed of 1 MHz and promises to have a lifespan of 15 years. It is advertised to sustain at least 100000 read/write accesses. This means (according to National Semiconductor, who I asked about this) datachanges on the whole chip. This isn't a whole lot really; running a tight loop you can exhaust this in approximately 3 seconds. Or to put this in another perspective, if you had a video game that would update the complete EEPROM after each game, you could play -safely- ca. 1500 games. It is therefore smart to minimize accesses to the EEPROM. I suggest that at the start of your code, you read the values from all of the cells that you are going to use (not all of the EEPROM) completely and keep a local copy. When ever you need to save changes, compare your data with the previous shadow copy and only update those cells that need it. The chip supports the following commands (excluded are two obsolete commands): READ: 1 1 0 0 n n n n n $180 This commando is used to address a cell (0-63) in the EEPROM and read 6 bits from it subsequently. WRITE: 1 0 1 0 n n n n n $140 Used inside a wrappage of LOCK/UNLOCK commands to write 16 bits into the cell. UNLOCK: 1 0 0 1 1 0 0 0 0 $130 Unlock the EEPROM for writing. LOCK: 1 0 0 0 0 0 0 0 0 $100 Prevent write accesses to the EEPROM. The chip boots up in this stage. WRITEALL: 1 0 0 0 1 0 0 0 0 $110 Initialize all the EEPROM cells with a 6 bit pattern. Also needs the LOCK/UNLOCK wrappage If you want to know the chip in excruciating detail get yourself the original documentation from National Semiconductor, we'll just provide a programmers destillation of what you need to know. Access to the EEPROM is provided via serial (bitwise) channel, that you have to bitbang. Commands are initiated by accessing EEPROM_STROBE, the chip is then listening to you and waiting for a command (if - special case - it isn't busy writing at the moment). After reading or writing you are then ready to toggle in the command bits in a MSB -> LSB fashion. The EEPROM can be toggled with a speed of 1 us. Since you are directly bitbanging the EEPROM chip you have to take its timing needs and characteristics into account. The EEPROM does not have an independent clock source, but is clocked by you the programmer twiddling a register. Lets assume you are using the 68000 to do the bitbanging. That chip is running at a 'velocity' of 13.3 Mhz, translating into a cycle time of 75ns. The EEPROM has a minimum cyle time of 1us, thirteen times slower! You can't write into it at full speed therefore. (A NOP takes 0.3 ns to execure, which means that a bit more than 3 NOPs can be executed in a minimum EEPROM cycle) HOW TO SEND A COMMAND TO THE EEPROM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. access EEPROM_STROBE, thereby initiating a command / status request, leave ns room until step 2 2. send 9 bits of command data most significant bit first to to the chip via EEPROM_WDATA. Give the EEPROM at least 1 us time between each access. HOW TO READ FROM THE EEPROM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Send READ ( 1 1 0 0 n n n n n (n being the cell number)) command to the EEPROM 2. now read 16 bits by toggling in the data via EEPROM_CLOCK. Start with a togggle, wait 500 ns and then read the bit in from the least significant bit of EEPROM_RDATA. HOW TO WRITE TO THE EEPROM ~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. send UNLOCK ( 1 0 0 1 1 0 0 0 0 ) command to unlock the EEPROM 2. send WRITE ( 1 0 1 0 n n n n n (n being the cell number)) 3. now send 16 bits of data over. The sending of the data bits is analogous to the sending of the command bits, but do not access EEPROM_STROBE! 4. Now access EEPROM_STROBE to initiate the actual 'burning' of data. That can take up to 10 ms. Wait 500 ns then check the LSB of EEPROM_RDATA repeatedly for the busy signal (0) to go away. 5. send LOCK ( 1 0 0 0 0 0 0 0 0 ) command to lock the cartridge Look at the EEPROM Tutorial for some snippets of code. R: EEPROM_STROBE $(F15000) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16 12 8 4 0 +---------^---------+---------^---------+ | | +---------------------------------------+ Accessing this register yields a CS (Chip Select) signal to the EEPROM, usually signalling that you are about to send some command data. This also has the pleasant side effect that the EEPROM will send its status (with a delay of up to 500ns) W: EEPROM_WDATA (F14800) R/W: EEPROM_CLOCK (F14800) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 2 8 4 +---------^---------+---------^------+--+ | unused |b | +------------------------------------+--+ 15..............................1 0 Accessing this register sends a clock cycle to the EEPROM. This is used to serially toggle bits into the EEPROM or to read bits from the EEPROM. The register serves a dual purpose in writing mode, since the least significant bit is the one being sent out. So for writing you just write a bit into this register and all is done for you. In reading mode you access this register first and then acquire the data via EEPROM_RDATA. R: EEPROM_RDATA (F14000) Same as JOYSTICK!! ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16 12 8 4 1 0 +---------^---------+---------^------+--+ | unused |b | +------------------------------------+--+ 15..............................1 0 After setting the EEPROM to read mode, you can serially read out the bits from this register. Or you can read the status of the EEPROM (after 500ns). Zero means busy. Atari Boot ROM =-=-=-=-=-=-=-= There's no JAGPEG code in the bootroms, because Atari supposedly wasn't able to finish it on time.
$Id: cartridge.html,v 1.19 1997/11/16 18:14:39 nat Exp $