-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
82-HACK.TXT Hacking the TI-82 calculator Version 1.1
Copyright (c) 1999 Mattias Lindqvist & Dines Justesen
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
By hacking the the TI82 calculator it is possible to run assembly programs,
which gives lot of new posibilities. This text file describes how to hack the
calculator. If you have comments, additions or corrections to this file
contact Dines Justesen at c958362@student.dtu.dk.
+-----------------------------------------------------------------------------
| TI-82 Memory Organization and Backups
+-----------------------------------------------------------------------------
The basis of TI-82 hacking is the memory backup. This backup can be
transferred to a PC where it can be modified, and then transferred back to the
calculator. The backup contains all variables that were in the TI-82 RAM when
the backup was made and miscellaneous system information. The dispositon of a
backup file, called BACKUP.82B is described in figure 1. Corresponding
addresses in TI-82 RAM are also given.
+---------------------------+ Backup File Offset TI-82 RAM Offset
| File Header | 0000-0023
+---------------------------+
| System Data | 0023-0841 8000-8D23
+---------------------------+
| User Data | 0842-xxxx 8D24-xxxx
+---------------------------+
| Variable Allocation Table | yyyy-End-3 yyyy-FE6E
+---------------------------+
| 2 Byte Checksum | End-2
+---------------------------+
Figure 1.
The Variable Allocation Table (VAT) is copied directly from the TI-82 RAM. It
contains information about a variable's name, type and address. The VAT is
built upside down (i.e. it starts at $FE6E and grows downwards in memory) and
each entry, except program variables, has the format below.
Under some conditions the system stores data right after the end of the
VAT, and ANS might be stored here too. The system might move all data
away from this location when a backup is made, but we do not know this for
sure
+------+--------+--------+------+------+------+
| Zero | Token2 | Token1 | AdrH | AdrL | Type |
+------+--------+--------+------+------+------+
Figure 2.
The Zero byte comes first in memory. However, since the VAT table is written
downwards in memory, the Type byte is the first byte of the entry. The type
byte tells what type of variable it is. The following types exist:
00 Real 05 Program
01 List 06 Protected Program
02 Matrix 07 Pic
03 Y-Var 08 GDB
(Other numbers are some times used, but most of these are only used in the header
of 82* files. See 82-VARS.TXT for a more complete list.) The 4 MSB of the type
is used by the system and can have any value, so maks these out before using the
type byte. AdrH and AdrL are the high and low byte respectively of the
variable's address in RAM. RAM starts at address $8000 and user RAM (where
variables are stored) starts at $8D24. Adresses are usually written Low byte
first (since it's a Z80 system) but in this case, since everything is backwards,
they appear to be High byte first.
Following after the address, there are two token bytes. All variable names,
except programs, are in the TI-82 stored as one or two bytes tokens. If a one
byte token is used, Token1 holds the token. If a two byte token is used the
token is placed in both Token1 and Token2. For instance 60 00 is the token for
PIC1, 60 01 for PIC2, etc. Almost all the tokens are the same on the TI82 and
the TI83, so refere to TI's information on the TI83 for a complete list of
tokens. 82-VAR.TXT conatains a list of tokens which are not the same on the
TI82 and TI83.
Finally, every VAT entry ends with a zero byte.
For each new variable created, a VAT entry is added to the table. As an
example of a VAT, consider the following fragment of a VAT:
00 18 5E 90 1C 03 00 19 5E 90 1A 03
We start from right: 03 indicates it's a Y-var. It's address in memory is
$901A and its token is 5E19 which equals Y0. Next one is also a Y-var, 5E18
which equals Y9. It's located rigth after the other one. This is the normal
case: consecutive VAT entries represent consecutive variables in memory.
The Y-VARS and a few other system variable are always present in memory, while
all other variables are put in when they are initialized. To prevent
fragmentation, when a variable is deleted, all variables that are stored after
the deleted var are moved down to fill the gap. The same happens with the VAT,
later entries are moved down (but up in memory!) one step. Of course the VAT
is also updated to reflect the new locations of the variables that were moved.
Knowing this, we can go on to...
+-----------------------------------------------------------------------------
| Altering arbitrary bytes in RAM
+-----------------------------------------------------------------------------
The method I used for this is similar to the method above for dumping ROM:
1. Create a REAL var.
2. Make a memory backup to a PC.
3. In backup.82b change the address of the REAL var, so that it points at the
RAM location you want to change.
4. Fix backup.82b checksum.
5. Transfer back to calc.
6. Voilą! You can now directly change the desired byte by storing various
values to the REAL var.
The format of a REAL var is the following:
+------+-----+----+----+----+----+----+----+----+
| Sign | Exp | M1 | M2 | M3 | M4 | M5 | M6 | M7 |
+------+-----+----+----+----+----+----+----+----+
Figure 4.
The MSB of the sign byte is the sign of the number, if it is cleared the
number is positive, if it is set the number is negative. The 4 LSBs are used to
store the type of the var which the real belongs to. The rest of the byte are
used by the system and can have any value. Exp is the REAL's exponent + $80.
E.g. if the exponent is -5 Exp has the value $7B. After that the 14 digit
mantissa follows stored in packed BCD format. I.e. every nibble represents one
digit. All numbers which have M1=00 are treaded as zero by some rutines.
There are some problems with this method. First, you always have to change 9
bytes at a time which can be hazardous if you're not cautios. Secondly, using
actual REAL vars you can only create quite limited byte patterns. For
instance, due to the packed BCD format of the mantissa, each nibble in M1-M7
can only contain values between 0-9 and not A-F. As everything else this can
also be solved. The solution is to:
1. Create another REAL on the calc.
2. Make a backup.
3. Change the value (not its address this time) of this REAL in backup.82b.
Here you can put in any values you like.
4. Transfer the backup back to the calc.
5. Store the second REAL into the first. When doing this TI-82 does not try
to verify that the contents of the source REAL is valid. It just copies
the bit pattern.
Another method which is useful for running ASM is to create a Matrix and modify
the addresse of it so it is placed in the ROM ! Then by writing to the correct
element of the Matrix it is possible to modify the system RAM. This method is
more efficient if more then one location in the RAM needs to be changed.
Changing the name of the variables you use for this to something you normally
would not use is also a good idea since this ensures that BASIC program wont
change them.
+-----------------------------------------------------------------------------
| Running Z80 machine code programs
+-----------------------------------------------------------------------------
The word at $8114 in TI-82 RAM is a pointer which contains the address to
which the TI-82 OS jumps to when a key is pressed. By changing this pointer
it is possible to get the processor to jump to any code in the RAM. The TI-82
Assembler Shell (Ash) is based on this fact.
The system part of the RAM contains other locations which is used like 8114,
but the function which these point to are executed when other events occur.
These locations could also be used to run asm code, but the value at 8114 is
the easiest to use. (see 82-VAR.TXT for more information)
(If you wonder how I ever figured out about the pointer at $8114: it was done
by recalling small parts of the ROM to PICS, transferring the pics to a PC and
there disassemble them. Hardly surprising it was very similar to the TI-85
ROM, with which I, thanks to many earlier TI-85 hackers, am quite familar
with. Thus it wasn't hard to tell what was happening inside the TI-82. For
more info on the ROM->PIC recalls see "Hacking the TI-85 calculator" [1]! )
In order to get an assembler program to run on TI-82 you need to store it
somewhere in the calculator's memory. TI-82 has no obvious variable type to
use for this, but PIC vars were first used. The easiest way to insert
the machine code into a PIC var is to first create a PIC on the calculator,
transfer the PIC to the PC, insert the asm code into to the PIC file and then
transfer it back to the calculator.
Here another problem arises; TI-82's memory is constantly moving around.
This is problematic since it is neccessary to know the exact address of the PIC
in order to jump to the code contained within it. This can however be solved by
moving the PIC var down in memory to the first byte of user memory ($8D24).
This way there will not be any variables in front of the PIC, and it will never
have to move around. Like with everything else, this is done by altering a
backup-file. What you do is the following:
1. By looking at the VAT, calculate what part of the backup-file is the PIC.
2. Move this part to $842 (= $8D24, see fig 1!) and move everything above
$842 up the size of the PIC var.
3. Update all pointers in the VAT (tedious!)
When this is done, you need to create two REAL vars, according to the method
described in the previous section. In one of these we store the address of
the PIC, $8D24. We don't use the data part of the second one, instead we
change its VAT entry to point to the key-press-pointer. For instance you can,
in a backupfile, change REAL var n:o 1 to 00 00 00 00 00 00 00 24 8D (remember
addresses are stored LSB first!). The reason for for putting 24 8D last is
that we don't want to destroy the bytes that comes after $8114-$8115. The
bytes before $8114 however doesn't contain anything important so it can be
overwritten with zeroes (they are not used on the homescreen). Now, in order to
get the key-press pointer to point at our PIC we first point REAL n:o 2 at
$810D ($8114-7, since var n:o 1 contains seven zeroes and then the address) and
after transferring the backup back to the calculator we type [REAL1]->[REAL2],
e.g: A->B. Next time you press a key, the code contained in the PIC will be
executed.
To return to the OS, first restore the key press pointer (set it to $411B) and
then make a RET.
The problem with using PICs for storing program is that the size them is fixed,
this makes it hard to make large programs, and wastes space when small programs
are made.
+-----------------------------------------------------------------------------
| Misc technical info about TI-82
+-----------------------------------------------------------------------------
The ROM of a TI-82 is 128k big. Since the Z80 can only address 64k and the 32k
of RAM also has to fit within these 64 k, the ROM has been divided into 8 ROM
pages ą 16 k. The address space is arranged according to figure 3.
+---------+
| Page0 | $0000-$3FFF
+---------+
| Page0-7 | $4000-$7FFF
+---------+
| RAM | $8000-$FFFF
+---------+
Figure 3.
ROM page 0 contains the ROM routines that are the most frequently used. The
second ROM area can contain any of the 8 ROM pages (16k each), depending on
what type of task the operating system is performing. The ROM switching
mechanism is connected to a port of the Z80 processor.
For more technical information I refer to the following documents.
- A programmer's guide to TI-82 RAM
- A programmer's guide to TI-82 ROM
- A programmer's guide to TI-82 PORTS
- A programmer's guide to TI-82 Variable Management
All files are available from ticalc.org and from the Ash site:
Footnotes:
------------------------------------------------------------------------------
[1] "Hacking the TI-85 calculator" by David Boozer. Available from ticalc.org.
[2] FIX.COM for fixing the checksum of *.82? files is appended (UUEncoded) in
Appendix A.
Credits to:
------------------------------------------------------------------------------
- David Boozer, who did ground-breaking work on TI-85 hacking
back in 1994
- Dan Eble < eble.2@osu.edu> who is the man behind ZShell and assembler on
the TI-85.
Appendix :
------------------------------------------------------------------------------
A UUEncoded copy of FIX.COM:
begin 644 fix.com
MOX``B@6*R#+M@_D`='E)1XH%/"!T\T&+][^2`?.DN`(]NI(!S2&+V')4M#^Y
M`("Z,0+-(:.0`7)%OV8"BPTSP#/2B_F!QV@"3XH5`\+B^8L^D`&!QR\"B06X
M`$(SR3/2S2%R&K1`BPZ0`;HQ`LTA<@VT";H4`LTAM#[-(OQ
MNO0!M`G-(