83Plus:OS:Variable Storage in the User Archive
The SDK doesn't have much information on this. The SDK mostly claims that you can't access in data in the archive without unarchiving it; this is untrue, for you can in fact access the data using FlashToRAM. But before that can work, you need to understand how data is stored in flash.
Archive
The user archive differs between the 83+, 83+SE, 84+, and 84+SE. The "archive" for programs, appvars, groups, lists, REALs, matrices, and every other data type grow upwards from page 08h. On the TI-83+, the last page of the archive is page 15h; on the TI-84+, the last page is page 29h; and on the TI-83+SE and TI-84, the last page is page 69h. You can read data from the archive using FlashToRAM, or though paging with port 6.
The flash memory is divided into sectors of groups of four pages. The flash chip can program any single bit from a 1 to a 0 at any time, but erasing from a 0 to a 1 can only be done on a per-sector basis. Each sector has a byte at the very beginning (4000h, pages 08h, 0Ch, etc.) which holds the status of that sector. The following values mean it is valid:
- 0FCh
- 0FFh
- 0F0h
The swap sector is also stored in this area, and it can be any full 64K sector. It is identified with the byte 0FEh.
After the status byte for that sector, the archived data begins. The 83+ SDK has some information on this, but it's repeated here. Each variable entry begins with three bytes:
Flag | sizeLow | sizeHigh
The flag byte will be 0FCh (valid) or 0F0h (deleted, ignore it). The size word can be used to skip to the next variable. After this will be the variable's VAT entry. Note that the VAT entries stored in RAM are stored backwards, but the VAT entries stored in flash are stored forwards.
T | T2 | Version | addressLow | addressHigh | Page | Name Length | (Name)
The address and page of this entry points to the flag byte at the start of the entry, not the start of the variable's data. Don't forget, most data types start with a size word, which will appear directly after the name.
Note that data can span multiple pages, but cannot cross sector boundries.
Example
This will search for a program, appvar, or group in the archive, and, if in the archive, return the amount of data in the item and location of the data. This code should work.
; Inputs: ; - OP1: name of variable ; Outputs: ; - A: Page data is on ; - HL: Pointer to data ; - DE: Size of data ; - T1 and T2 can be found at 8003h and 8004h. B_CALL ChkFindSym jr c, errorNotFound ld a, b or a jr z, itemIsInRAM push de ex de, hl ld de, 8000h ld bc, 30 B_CALL FlashToRAM ld a, (8009h) ld hl, 800Ah add l, a ; note that you must change this to a 16-bit add if you move the above address ld e, (hl) inc hl ld d, (hl) ld a, (8008h) pop bc res 7, h add hl, bc bit 7, h ret z res 7, h inc a ret errorNotFound: ; Oh no! itemIsInRAM: ; Getting the data is now much easier.
Adding to Archive
Start at page 08h and access the status byte. If it is 0FEh, skip to the next sector (4 pages). If you find any other status byte, abort.
Once you've found a valid sector, start reading each entry by checking the status byte (0FCh for exists, 0F0h for deleted). Then read the size and add it to your current location to find the next VAT entry (it can and will span to the next page and sector (don't forget the status byte)).
Whenever you find 0FFh, stop and add an appropriate VAT entry and data. Make sure there's enough space left on the sector to write your data.
Don't write directly to flash unless you know what you're doing.
Applications
Applications are stored at the top of the archive and grow downward. On the 83+, the top page is 15h; on the 84+, it is 29h, and on the 83+SE/84+SE it is at 69h. The following status bytes are used on each base page:
0FFh = empty. 080h = valid Flash application (this is part of the app header). 000h = deleted Flash application (this is part of the app header).
If there is one multipage application on the 84+SE, for example, then the first byte of page 69h is 080h, and page 68h will contain the second page of the application. THE FIRST BYTE OF THIS PAGE HAS NO MEANING. To traverse this, you must access the Flash application's number of pages on the base page (offset 401Ch) and use this to go backwards a certain number of pages.
The first page to contain 0FFh as its first byte is the first empty one. Applications are never fragmented, so when you see 0FFh, there are no more applications. Applications and archive data never occupy the same sector.
Credits and Contributions
- Brandon Wilson, for originally writing most of this up.