31
ASM / Documentation dump
« on: January 05, 2011, 07:51:28 pm »
What I have here is for someone on the omni chat room. It explains a little about the VAT. If you find this useful, move this topic to some other place.
If you want, here's some code that'll perform a sort on the program VAT. My hope is that it'll help you better understand code that works with the VAT:
The following bit of source comes right out of Celtic III. It searches the VAT for some given variable in Op1. It's supposed to be a replica of the ChkFindSym romcall, but I wrote it because I wanted something faster than a romcall. I believe this code searches both the Symbol Table and the Program/List VAT structures.
Code: [Select]
On the TI-83 Plus graphing calculator, there are three different tables used to
allocate memory to programs, or to determine the presence of each program or
variable to the calculator. For the reason the table exists, it's often times
called the "VAT", or "Variable Allocation Table". Usually, this name is given to
the second part of the entire table, or to be most specific, the first part of the
table, with a fixed beginning, is called the "Symbol VAT" and the next part is
called the "Program VAT", but some people would call it the "Symbol Table" and the
"VAT", respectively. The third part, which few people know about, is the Temporary
Variable section, which is pointed to by (pTemp). (pgmPtr) points to the Program
VAT.
All entries on any table are written in backwards, from high memory to low memory.
All entries on Program VAT vary depending on the name length
==============================================
| -(n+6) -6 -5 -4 -3 -2 -1 0 |
==============================================
| VarName N.Len Page DadrH DadrL Ver T2 T |
==============================================
VarName can be up to 8 characters in length
T= first five bits are datatype,
b5= graph equ selected
b6= variable used during graphing
b7= link transfer flag
T2=for future use [TI-OS keeps it at ZERO]
Ver= version code to not recieve if higher than current OS code
DadrL = data address, LSB
DadrH = data address, MSB
Page = if archived, holds flash page. Otherwise, = 0
N.Len = following name's length. For lists, this includes token and formula #
For lists, the name can be up to 5 characters in length.
Preceding the name is the list token ($5D), and postceding it is the formula number, which is
set to zero if there is no formula attached. If there is, then a number will be given to point
to a corresponding unique name for an EQU variable in the Symbol VAT.
All entries on the Symbol VAT are fixed in size.
==============================================
| -8 -7 -6 -5 -4 -3 -2 -1 0 |
==============================================
| 0 Tok2 Tok1 Page DadrH DadrL Ver T2 T |
==============================================
Tok1 = first token of name
Tok2 = second token of name
A symbol table entry for a formula would be where:
Tok1 = $3F
Tok2 = F, where "F" would be the corresponding function # found with the list.
If you want, here's some code that'll perform a sort on the program VAT. My hope is that it'll help you better understand code that works with the VAT:
Code: [Select]
#define equ .equ
#define EQU .equ
#define EQU .nostub
.org $9D93
.dw $6DBB
;Program used to sort the Program/List VAT alphabetically
;(progPtr) is the start of the VAT. First order of business is to determine
;how many entries are in the VAT. Then we can go ahead and blindly sort the
;entire contents of the VAT.
;Checking against (pTemp) at the end of the run. Gets us this manieth entries
;
;
#define bcall(xxxx) rst 28h \ .dw xxxx
_DispHL EQU 4507h
pTemp EQU 982Eh
progPtr EQU 9830h
tempSwapArea EQU 82A5h
curptr equ tempswaparea ;2 bytes, current location in the VAT
swaptemp equ curptr+32 ;up to 30 bytes for temporary swapping. Backwards
ProgramStart:
ld ix,0
ld bc,(ptemp)
ld hl,(progPtr)
ProgramLoop1:
call GetNextEntry
inc ix
push hl ;preserve HL for the check.
or a
sbc hl,bc ;checking to see if it's at the end.
pop hl
jr nz,ProgramLoop1 ;If end of VAT is not current pointer, keep going.
push ix
pop bc
ProgramLoop2:
ld hl,(progPtr) ;pointer to the start of the VAT, to start off with each run
dec bc
ld a,b
or c
ret z ;Kill routine if there's no more entries to sort through
push bc ;saving this variable for later...
ProgramLoop3:
push bc ;save loop counter for VAT traversal
push hl ;save current address to the VAT location
ld de,-6 ;to get to...
add hl,de ;...file name size of this VAT entry
ld c,(hl) ;getting size of entry #1 into C
push hl ;saving first address point
ld a,c ;
cpl ;getting past name and first decrement
add a,e ;-6+-1+-sizeofcurrenname = entry #2 name size
ld e,a ;Hehe. Loading this back into DE
add hl,de ;now at size of second file
ld b,(hl) ;And putting filename size #2 into B
dec hl ;moving HL to the filename's start (#2)
pop de ;DE is 1st file, HL is second file. Starting at their names.
dec de ;moving DE to the filename's start (#1)
ld a,c ;Start comparison of namelength fields.
cp b ;C=(#1) B=(#2); C-B. Carry if C is shorter
ld a,1 ;If first name is longer, then perform swap if all is equal
jr nc,$+4 ;If B(#1) is shorter (NC), skip. Else, set B to short and...
dec a ;...reset A to indicate no swap.
ld b,c ;Set B to the lowest possible
ld c,a ;Resetting C to function as a flag. Should it swap is the anser.
ProgramLoop4:
ld a,(de) ;1st file
cp (hl) ;2nd file.
dec de ;get next characters in the file names.
dec hl
jr nz,$+6 ;if the names do not match, jump past to continuation...
djnz ProgramLoop4 ;only iterating for shortest number of characters.
jr ProgramSkip5 ;If no more chars, do default swap action from last rtn.
ld c,0 ;Remove flag from previous routine. Diff in name means...
jr c,ProgramSkip5 ;(1f)-(2f) If carry, no swap needed.
inc c ;else, start up the routine used for swapping.
Programskip5: ;we have our flags now. 0 for noswap, 1 for swap
pop hl ;get back current VAT address (starting)
ld (curptr),hl ;save this for future reference.
call GetNextEntry ;getting the next entry from HL
dec c ;checking for zero. If so, a swap is in order...
jr nz,ProgramSkip6 ;if jump is taken, skip the swapping business
ld de,swaptemp ;loading the temporary writeout address
call CopyEntry ;copy second entry
ld hl,(curptr) ;get back the first entry location
push hl ;Save it as the location to write back to.
call CopyEntry ;copy the first entry as second into the buffer
ld hl,swaptemp ;loading higher address to HL and prepare for subtraction
or a ;clear out carry flag so sbc isn't affected.
sbc hl,de ;Subtract to get the size difference (number of bytes)
ld b,h ;number of bytes total to copy
ld c,L
pop de ;back to first entry location
push de ;save that sucker again.
ld hl,swaptemp ;point to the start of the temporary buffer location
lddr
pop hl
call GetNextEntry ;getting the NEW next entry
ProgramSkip6:
pop bc
dec bc
ld a,c
or a
jr nz,ProgramLoop3
pop bc
jr ProgramLoop2
CopyEntry:
ld bc,6 ;write and decrement HL and DE the first 5 bytes of VAT entry.
lddr ;Uh. yeah.
ld a,(hl) ;Get that sixth byte, which is size field
inc a ;Another for this byte as well...
ldd ;Perform one LDD for each byte of the name and the size field as...
dec a ;...indicated by this number.
jr nz,$-3 ;And loop until the entire things is written out into the buffer
ret
GetNextEntry:
ld de,-6 ;go ahead and skip past current entry...
add hl,de ;
ld a,(hl) ;get those size bytes.
cpl ;and as we did before
ld e,a ;add them together with the CPL's autodecrement
add hl,de ;and we're at the start of entry #2.
ret
.end
The following bit of source comes right out of Celtic III. It searches the VAT for some given variable in Op1. It's supposed to be a replica of the ChkFindSym romcall, but I wrote it because I wanted something faster than a romcall. I believe this code searches both the Symbol Table and the Program/List VAT structures.
Code: [Select]
SearchVAT:
ld hl,(Op1)
ld h,$00
ld de,SearchVTbl
add hl,de
ld a,(hl)
or a
jr nz,SearchVP
SearchVS:
ld hl,(progptr)
ld de,-6
add hl,de
ex de,hl
ld hl,symtable-6
ld bc,-9
SearchVSL:
push hl
ld a,(Op1+1)
cp (hl)
dec hl
jp nz,SearchVSN
ld a,(Op1+2)
cp (hl)
dec hl
jp nz,SearchVSN
ld a,(Op1+3)
cp (hl)
dec hl
jp nz,SearchVSN
ld bc,4
add hl,bc
ld b,(hl)
inc hl
ld d,(hl)
inc hl
ld e,(hl)
jr SearchVSE
SearchVSN:
pop hl
add hl,bc
or a
sbc hl,de
add hl,de
jp nz,SearchVSL
scf
ret
SearchVSE:
pop hl
ld a,(Op1)
or a
ret
SearchVP:
ld hl,Op1+1
xor a
ld c,a
cp (hl)
jr z,$+8
inc hl
inc c
bit 3,c
jr z,$-7
ld hl,(progptr)
ld de,-6
SearchVPL:
ld a,(Op1)
cp (hl)
jr nz,SearchVPS
push hl
ld de,Op1+1
ld b,c
ld a,(de)
cp (hl)
jr nz,SearchVPSP
inc de
inc hl
djnz $-6
pop hl
push hl
dec hl
dec hl
dec hl
ld e,(hl)
dec hl
ld d,(hl)
dec hl
ld b,(hl)
pop hl
or a
ret
SearchVPSP:
ld de,-6
pop hl
SearchVPS:
add hl,de
push de
ld a,(hl)
neg
ld e,a
add hl,de
ld de,(ptemp)
or a
sbc hl,de
add hl,de
pop de
jr nz,SearchVPL
scf
ret
SearchVTbl:
.db 0 ;00 real
.db 1 ;01 list
.db 0 ;02 matrix
.db 0 ;03 equation
.db 0 ;04 string
.db 1 ;05 program
.db 1 ;06 protected program
.db 0 ;07 picture
.db 0 ;08 graph database
.db 0 ;09 unused
.db 0 ;0A unused
.db 0 ;0B new equation
.db 0 ;0C complex
.db 1 ;0D complex list
.db 0 ;0E unused
.db 0 ;0F unused
.db 0 ;10 unused
.db 0 ;11 unused
.db 0 ;12 unused
.db 0 ;13 unused
.db 0 ;14 application. Passthrough.
.db 1 ;15 appvar
.db 1 ;16 temporary program
.db 1 ;17 group