Difference between revisions of "84PCE:OS:Applications"
(→Additional App Structure) |
(→Additional App Structure) |
||
Line 134: | Line 134: | ||
024h = Offset to the string used to display a message in the memory screen (Usually a copyright, i.e. "(c) 2005-2015 Texas Instruments") | 024h = Offset to the string used to display a message in the memory screen (Usually a copyright, i.e. "(c) 2005-2015 Texas Instruments") | ||
− | 027h = | + | 027h = Reserved word |
+ | |||
+ | 02Ah = Start of relocation table | ||
== ExecLib == | == ExecLib == |
Revision as of 22:37, 1 October 2017
Contents
Application File Type
Applications for the CE calculator have the extension 8ek.
Relocations exist to place the app correctly in the archive, 6 bytes per block (2+22 bits):
0b00 indicates a reference to the code segment executing from Flash, and 0b10 indicates a reference to the data/bss segment in RAM. 0b01 and 0b11 are a reserved format;
Applications can be of arbitrary size, no longer multiples of 16kB.
Applications in the Archive
Applications are stored beginning at the address 03B0000h and grow downwards. 3 bytes are used as offsets to the start of the app, since the search is backwards. The following status bytes represent what might be found when parsing for applications:
081h = valid Flash application (part of the app header)
000h = deleted Flash application (part of the app header)
Some search code may look like this (Will locate the start of all the app headers):
_FindValidLocation: ld hl,03B0000h ; applications start here find: dec hl dec hl dec hl push hl ld de,(hl) ld hl,0FFFFFFh ; check for end or a,a sbc hl,de pop hl ret z ; found end of applications or a,a sbc hl,de ; hl points to the start of the app header here if found jr find
The actual App header contains certain fields which correspond to the type of data they represent. TI dropped the ball and even though these are variable length fields, the OS code can only handle headers that are padded to 256 bytes in length.
810(F)h = Master field, 4 bytes in length, which contains the offset to the signature field. (Big Endian)
811(2)h = Signing key ID. On the CE, this is 2 bytes in length with the value 0130Fh, indicating it was signed with the '130F' key.
812(D)h = Version information. Begins with the length of the version string, followed by the string itself. This is a minimum compatible version.
813(2)h = Unknown, but contains the 2 byte data 05900h.
814(N)h = Name of App. In this case, 'N' represents the length of the name in bytes. This field is then followed by the name of the app.
817(F)h = End app header information, 4 bytes in length, which contains the offset to the signature field. (Big Endian)
81A(1)h = Unknown, but contains the 1 byte data 007h
Other fields:
003h & 2(6)h & 009h & 0(4)h = Time stamp field. 4 bytes long; represents the number of seconds since January 1st 1997, 00:00:00 in some timezone, and some step of the build process.
00Dh & 0NNh = This (NN) represents how much padding until the next field, as app headers must be padded to 256 bytes.
002h & 03(E)h = Signature field. The is followed by the two bytes containing the value 0100h, the length of the 2048 bit signature
At the end of the signature is 3 bytes representing the size of the application. (These bytes are not included however)
App size calculation is as follows: [Length of master header + offset to signature field in (810)] + [4 bytes of signature field + 256 bytes of signature] + [3 bytes application size]
This is pretty much the same as adding 269 to the value in the big endian master field.
This is an example of such a header:
; Master Field -- This app is 102247 + 269 (102516) bytes in size .db 081h, 00Fh, 000h, 001h, 08fh, 067h ; Signing Key Field .db 081h, 012h, 013h, 00Fh ; Version information -- 00Bh represnets the length until the next field .db 081h, 02Dh, 00Bh, "5.0.0.0089", 000h ; Unknown field .db 081h, 032h, 059h, 000h ; Name Field -- Name is 7 bytes long, so that is where the 047h comes from .db 081h, 047h, "CabriJr" ; Unknown field .db 081h, 0A1h, 007h ; Time stamp -- Who knows what time is was? .db 003h, 026h, 009h, 004h .db 021h, 0BBh, 06Eh, 0DCh ; Amount of pading (This is so, so silly) .db 000h, 00Dh, 0C7h ; Padding of 0C7h (199) bytes .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .db 0,0,0,0,0,0,0 ; Final field .db 081h, 07Fh, 000h, 001h, 08Eh, 06dh ; End of 256 byte header
Additional App Structure
However, apps are also made up of a certain sequence of bytes following the header. Offsets are calculated from the posistion after the header, in addition to the offsets derived from offsets.
Offset after 256 byte header:
000h = The ASCII string "eZ8", potentially signifying an eZ80 application
003h = Null terminated Application name (zero padded to be 9 bytes in length with terminator byte)
00Ch = Flag, [Bit 0 set - don't draw the TI splash screen] [Bit 1 set - app can use OpenLib]
00Eh = Flag, [Bit 0 set - use the offset in 01Eh] [Bit 3 controls something]
012h = Main section
015h = Initialized data section (Can be at most 4kB in size)
018h = Initialized data section Length
01Bh = Execution entry point (usually same as 012h)
01Eh = Unknown 3 byte offset (See 00Eh)
021h = Offset to ExecLib jump table
024h = Offset to the string used to display a message in the memory screen (Usually a copyright, i.e. "(c) 2005-2015 Texas Instruments")
027h = Reserved word
02Ah = Start of relocation table
ExecLib
In order to use ExecLib properly from BASIC programs, you must:
1. Set the proper bit at offset 00Ch.
2. Initialize offset 021h to the start of the library jump table
3. Ensure that the jump table offsets are stored in the relocation table
The format for the jump table is shown below: (Note that you store AppLibraryTable offset to 021h).
.db "LIB" .dl NUMBER_OF_FUNCTIONS_IN_JUMP_TABLE AppLibraryTable: .dl Function_1 .dl Function_2 ...
Relocations
Because apps are not stored at a fixed memory address, they require a relocation table to relocate them during sending and defragmentation.
Example
Here is a full demo program demonstrating finding each application, displaying the name, size, version, and copyright information
#include "ti84pce.inc" .db tExtTok,tAsm84CECmp .org usermem ;-------------------------------------------------------------------- ; Finds all the apps and displays info _FINDAPPS: ld ix,0 add ix,sp ld hl,ExecuteApp ld de,cursorImage ld bc,ExecuteApp_End-ExecuteApp_Start ldir call _ZeroOP3 ld a,appObj ld (OP3),a _: call _HomeUp call _ClrScrn call _OP3ToOP1 call _FindAppUp ; find the app ret c call _OP1ToOP3 ; store name ld hl,OP1+1 push hl call _PutS ; put name of app pop hl ; don't need this push/pop (here for readability) call _FindAppStart ; find the start of the app push hl call GetAppSize call _DispHL ; display the size of the app call _NewLine pop hl push hl push hl call _os_GetAppVersionString pop bc call _PutS call _NewLine pop hl call FindAppInfoString ; Get the information call _PutS _: call _GetCSC or a,a jr z,-_ cp a,sk2nd jr nz,--_ ld hl,OP3+1 jp cursorImage ;-------------------------------------------------------------------- ExecuteApp: ; HL -> name of app (0 terminated) ; An alternative would be to copy to progtoedit and call _NewConext0 .org cursorImage ExecuteApp_Start: push hl call DeletePgrmFromUserMem ld hl,$100 call _EnoughMem pop hl jp c, _ErrMemory call _FindAppStart ; This locates the start of executable code for an app ld a,E_Validation jp c,_JError ; If we can't find it, that's a problem (throw a validation error) push hl ; push location of start of app call _ReloadAppEntryVecs call _AppSetup set appRunning,(iy+APIFlg) ; turn on apps set 6,(iy+$28) res 0,(iy+$2C) ; set some app flags set appAllowContext,(iy+APIFlg) ; turn on apps ld hl,$D1787C ; copy to ram data location ld bc,$FFF call _MemClear ; zero out the ram data section pop hl ; hl -> start of app push hl ; de -> start of code for app ld bc,$100 ; bypass header information add hl,bc ex de,hl ld hl,$18 ; find the start of the data to copy to ram add hl,de ld hl,(hl) call __icmpzero ; initialize the bss if it exists jr z,+_ push hl pop bc ld hl,$15 add hl,de ld hl,(hl) add hl,de ld de,$D1787C ; copy it in ldir _: pop hl ; hl -> start of app call FindStartOfAppCode ; After this, hl -> start of code for app jp (hl) ;---------------------------------------------------------------------------- FindAppInfoString: ; Finds the information string about an App ; i.e. (c) 2005-2014 Texas Instruments ; Arguments: ; HL : contains start of app address ld bc,$100 ; bypass some header info add hl,bc push hl pop de ld bc,$24 add hl,bc ld hl,(hl) ; load location of info string add hl,de or a,a sbc hl,de ; check if HL is 0 ret z add hl,de ; add extra bytes ret ;---------------------------------------------------------------------------- FindStartOfAppCode: ; Finds the start of the actual executable from the start of an App ; Arguments: ; HL : contains the start of the app address ld bc,$100 ; bypass some header info add hl,bc push hl pop de ld bc,$1B ; offset add hl,bc ld hl,(hl) add hl,de ret ;---------------------------------------------------------------------------- DeletePgrmFromUserMem: ld de,(asm_prgm_size) ; load total program prgmSize or a,a sbc hl,hl ld (asm_prgm_size),hl ; delete whatever current program was there ld hl,userMem jp _DelMem ; HL->place to delete, DE=amount to delete ;---------------------------------------------------------------------------- GetAppSize: ; Gets the size of an app based from the start of the app push hl call _NextFieldFromType ; move to start of signature call _NextFieldFromType ; move to end of signature pop de or a sbc hl,de inc hl inc hl inc hl ; bypass app size bytes ret ; haha, we're probably looking at another app here ExecuteApp_End:
Credits and Contribution
Matt "MateoConLechuga" Waltz