----------------------------------------------------------------------------- ----------------------------------------------------------------------------- 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-(