# -------------------------------------------------------------------
# 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.htm,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

  • Server Interface

  • Cartridge

  • EEPROM

  • Atari Boot ROM
  • 
    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.
    
    
    
    

    Nat! (nat@zumdick.ruhr.de)
    Klaus (kp@eegholm.dk)

    $Id: cartridge.htm,v 1.19 1997/11/16 18:14:39 nat Exp $