[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: IIGS battery ram format, reading, writing?



Here is some notes I came across for all who want to copy and paste this into your documents.

//gs Battery RAM and Clock/Calendar

There are 256 bytes of RAM inside the clock chip in the Apple //gs. These bytes are backed up by the same battery that keeps the clock ticking when you turn off your Apple. You can read and write the battery RAM locations, but not the same as regular RAM. You can either do it the hard way, by direct hardware, or you can do it through the built-in firmware.
First, the easy way. When you turn on your //gs, the power-up routines install a lot of stuff in RAM in banks $E0 and $E1. At the beginning of $E1 there are a lot of JMP opcodes, with long (24-bit) addresses. The one at $E10000 is a jump to the Tool Locater. The Tool Locater is simply a way to access a lot of firmware subroutines without knowing their actual addresses. Instead of calling a firmware subroutine directly, you load up a subroutine number in a register and call the single known address, $E10000.
To keep things organized, the //gs firmware designers require you to call $E10000 with the 65816 in Native mode, with a JSL $E10000. Any parameters the subroutines need must be pushed onto the stack before the JSL, and any results will be on the stack when the subroutine is finished. The carry status will indicate whether the subroutine returned an error code or not, just as in ProDOS MLI. If carry is clear, there was no error; if carry is set, there was an error and the error code is in the A-register. Regardless of the setting of the m- and x-status bits when you call $E10000, it will return with both of them zero (full 16-bit mode).
You tell the Tool Locater which "tool" to call by a code number in the X-register. This is a 16-bit value, so you must have 16-bit mode on for the X-register when you call $E10000 (x-status bit=0). It doesn't matter whether m-status is 0 or 1. The tool code is made up of a tool set number (00-FF, in the low byte) and a tool number (00-FF, in the high byte). The tool code to read all 256 bytes of battery RAM is $0A03; to write 256 bytes out to battery RAM, the tool code is $0903. The following program will read battery RAM:

  1000 *SAVE S.BATTERY.RAM
  1010 *--------------------------------
  1020        .OP 65816
  1030 *--------------------------------
  1040 R      CLC
  1050        XCE
  1060        REP #$30
  1070 *--------------------------------
  1080        PEA BUF/256/256
  1090        PEA BUF
  1100        LDX ##$0A03  READ BATTERY RAM
  1110        JSR $E10000
  1120 *--------------------------------
  1130        SEC
  1140        XCE
  1150        RTS
  1160 *--------------------------------
  1170 W      CLC
  1180        XCE
  1190        REP #$30
  1200 *--------------------------------
  1210        PEA BUF/256/256
  1220        PEA BUF
  1230        LDX ##$0903  WRITE BATTERY RAM
  1240        JSR $E10000
  1250 *--------------------------------
  1260        SEC
  1270        XCE
  1280        RTS
  1290 *--------------------------------
  1300 BUF    .EQ $900
  1310 *--------------------------------

When I did this on my //gs prototype, this is what I got:
     0900-00 00 00 01 00 00 0d 06 02 01 01 00 01 00 00 00-................
     0910-00 00 07 06 02 01 01 00 00 00 00 0F 07 00 08 0B-................
     0920-01 01 00 00 00 00 01 01 05 00 00 00 03 02 02 02-................
     0930-00 00 00 00 00 00 00 0C 08 00 01 02 03 04 05 06-................
     0940-07 0A 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D-................
     0950-0E 0F FF FF FF FF FF FF FF FF FF FF FF FF FF FF-................
     0960-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-................
     0970-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-................
     0980-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-................
     0990-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-................
     09A0-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-................
     09B0-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-................
     09C0-C2 CF C2 A0 D3 C1 CE C4 C5 D2 AD C3 C5 C4 C5 D2-BOB SANDER-CEDER
     09D0-CC CF C6 A0 FF FF FF FF FF FF FF FF FF FF FF FF-LOF ............
     09E0-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-................
     09F0-FF FF FF FF FF FF FF FF FF FF FF FF 27 CE 8D 64-............'N.d

Those last four bytes are some kind of a check sum, handled automatically by the tool. I suppose that if the checksum is incorrect on power up, you will be popped into the configurator instead of going into a boot. You can read these bytes, but you cannot write them with the tool: the tool will calculate a checksum and write it when you write the other 252 bytes. Bytes $52 through $FB are either used by the operating system or reserved for the future. Just for fun, I have now written my own name in ASCII code into the bytes starting at $C0.
The rest of the bytes are used as shown in the following table. Where two choices are shown, separated by a slash, the left one has a code of $00 and the right choice has a code of $01.

     Port 1   Port 2
      $00      $0C     Printer/Modem
      $01      $0D     Line Length (Any/40/72/80/132)
      $02      $0E     Delete LF after CR (No/Yes)
      $03      $0F     Add LF after CR (No/Yes)
      $04      $10     Echo (No/Yes)
      $05      $11     Buffer (No/Yes)
      $06      $12     Baud Rate
      $07      $13     Data & Stop Bits
      $08      $14     Parity
      $09      $15     DCD Handshake (No/Yes)
      $0A      $16     DSR Handshake (No/Yes)
      $0B      $17     XON-XOFF Handshake (No/Yes)

     Display Parameters
       $18     Color/Monochrome
       $19     40/80 Column
       $1A     Text Color (00-0F)
       $1B     Background Color (00-0F)
       $1C     Border Color (00-0F)
       $1D     60/50 Hertz Operation
       $29     Text Language (0=English)
       $2F     Flash Rate

     Keyboard Parameters
       $2A     Language (0=English)
       $2B     Buffering (No/Yes)
       $2C     Repeat Speed
       $2D     Repeat Delay
       $30     Shift Caps-LowerCase (No/Yes)
       $31     Fast Space-Delete Keys (No/Yes)
       $32     Dual Speed (Normal/Fast)

     Slot Configuration
       $21-27  Slot 1-7 Internal/External
       $28     Boot Slot

     Miscellaneous
       $1E     User Volume
       $1F     Bell Volume
       $20     System Speed (Normal/Fast)
       $2E     Double-Click Time
       $33     High Mouse Resolution
       $34     Date Format
       $35     Time Format
       $36     Min RAM for Ramdisk
       $37     Max RAM for Ramdisk
       $38-40  Count & Languages
       $41-51  Count & Layouts
       $80     AppleTalk Node Number
       $81-A1  Operating System Variables

It is possible, as I said before, to talk directly to the battery RAM via I/O addresses. If you learn how to do this, and you use the skill to write values into battery RAM, you will probably do so without properly changing the checksum. In that case you have violated your system, and your next power-up will revert to default values for all parameters. It will stay that way until you reconfigure everything and/or install a proper checksum. The best policy is to use the standard firmware tools for all reading and writing, so that the checksum stays current.

You do not have to read or write the whole battery RAM at once. There are two tools for reading and writing a single byte. Tool Code $0B03 will write one byte, and tool code $0C03 will read one byte. The following code segments illustrate how to do it. The code as shown must be in Native Mode, with both x- and m-bits zero (full 16-bit mode).

   WR  PEA $00xx     xx is new value for byte
       PEA $00yy     yy is address in battery RAM
       LDX ##$0B03   write xx at yy
       JSL $E10000
   -----
   RD  PEA $0000     make room for result
       PEA $00yy     yy is address in battery RAM
       LDX ##$0C03   read value at yy
       JSL $E10000
       PLA           get result from stack (00xx)

The Clock/Calendar Chip not only contains the battery RAM; it also contains the date and time information, naturally. There are three tools for reading and writing the time and date. You can read time/date in either hexadecimal format or as an ASCII string, and you can write a new time/date in a hex format. The following code segments illustrate how to use the tools.
Read.Time.Into.ASCII.String

       PEA BUFFER/256/256  Hi 16-bits of buffer address
       PEA BUFFER          Lo 16-bits of buffer address
       LDX ##$0F03         Tool Code
       JSL $E10000

The date and time will be converted to ASCII (with msb = 1) and stored in BUFFER, according to the formats selected in the configuration menu (stored in battery RAM locations $34 and $35). The most likely choice among North Americans will be the format "mm/dd/yy HH:MM:SS xM", but you have five other possibilities.

Read.Time.Hex
       PEA 0   Make room for 8 bytes
       PEA 0   to be returned
       PEA 0
       PEA 0
       LDX ##$0D03
       JSL $E10000
       PLA     Get $MMSS (minutes, seconds)
       STA MMSS
       PLA     Get $yyHH (year, hours)
       STA YYHH
       PLA     Get $mmdd (month, day)
       STA MMDD
       PLA     Get day of week (in low byte)
       STA DOW

The value for day of week runs from 0 to 6, with 0=Sunday. The value for "day" is 0-30, meaning that you have to add 1 to get the true day number. (Why? This is a little ridiculous!) Likewise, the value for month is 0-11, with 0 standing for January. (I can understand why the hardware might work with 0-based values for day and month, but why couldn't the firmware do the correction to "real" day and month numbers?) The year is specified as the actual year number minus 1900. I hope that means my //gs will still give correct dates after 1999. If the value of the "yy" byte can go all the way to 255, then we could use //gs until the end of the year 2155. Frankly, I think I'll get tired of computers before then.
To write a new date and time out to the Clock chip, you have to push the values onto the stack and call the tool:
Write.New.Time

       PEA $mmdd    month, day
       PEA $yyHH    year, hour
       PEA $MMSS    minute, second
       LDX ##$0E03
       JSR $E10000

Again, the month and day values are zero-based. Note that you cannot update the day-of-week directly; apparently it is only a CALCULATED value provided when you READ the date/time in hex format.
You might wonder whether anyone would really NEED all the above information. After all, Apple has provided the configuration system to see/modify all those parameters. The problem is you cannot really use that system unless you can SEE. A lot of Apple owners are not able to see, so they use the ECHO or other some other brand of speech synthesizer to speak everything that goes out to the screen. The configuration program cannot be made to speak, as it is now written.