Difference between revisions of "84PCE:OS:Applications"

From WikiTI
Jump to: navigation, search
(Applications in the Archive)
(Application File Type)
 
(28 intermediate revisions by the same user not shown)
Line 12: Line 12:
  
 
==Applications in the Archive==
 
==Applications in the Archive==
Applications are stored beginning at the address 03B0000h and grow downwards. The following status bytes represent what might be found when parsing for applications:
+
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:
 
+
0FFh = empty (this signifies the end of the available applications)
+
  
 
081h = valid Flash application (part of the app header)
 
081h = valid Flash application (part of the app header)
Line 20: Line 18:
 
000h = deleted 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.
 
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.
+
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.
 
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.
Line 33: Line 49:
 
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.
 
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 of main header information, followed by the length to the signature field
+
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
 
81A(1)h = Unknown, but contains the 1 byte data 007h
Line 63: Line 79:
 
  ; Unknown field
 
  ; Unknown field
 
  .db 081h, 032h, 059h, 000h
 
  .db 081h, 032h, 059h, 000h
  ; Name Field -- Name is 3 bytes long, so that is where the 043h comes from
+
  ; Name Field -- Name is 7 bytes long, so that is where the 047h comes from
 
  .db 081h, 047h, "CabriJr"
 
  .db 081h, 047h, "CabriJr"
 
  ; Unknown field
 
  ; Unknown field
Line 90: Line 106:
 
  ; End of 256 byte header
 
  ; End of 256 byte header
  
==Additional App Stricture==
+
==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.
 
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.
Line 98: Line 114:
 
000h = The ASCII string "eZ8", potentially signifying an eZ80 application
 
000h = The ASCII string "eZ8", potentially signifying an eZ80 application
  
003h = Application name (zero padded to be 9 bytes in length)
+
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
+
00Ch = Flag
  
00Eh = Flag, Bit 0,1
+
[Bit 0 - Disable TI splash screen]
 +
[Bit 1 - App can use OpenLib]
  
012h = Offset to main code block section (this also points to the end of the relocations table)
+
00Eh = Flag
  
015h = Offset to the initialized data section which should be copied to ram (Can be at most 4kB in size)
+
[Bit 0 - Use offset 01Eh for languages]
 +
[Bit 1 - Integrated app]
 +
[Bit 2 - Unknown]
 +
[Bits 3-5 control something]
  
018h = Length of the initialized data section
+
012h = Main section
  
01Bh = Offset to the execution entry point
+
015h = Initialized data section (Can be at most 4kB in size)
  
01Eh = Unknown
+
018h = Initialized data section Length
 +
 
 +
01Bh = Execution entry point (usually same as 012h)
 +
 
 +
01Eh = Unknown 3 byte offset used in Language apps (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")
 
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 = Unknown offset -- 3 bytes
+
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).
 +
 
 +
<pre> .db "LIB"
 +
.dl NUMBER_OF_FUNCTIONS_IN_JUMP_TABLE
 +
AppLibraryTable:
 +
.dl Function_1
 +
.dl Function_2
 +
...</pre>
 +
 
 +
== Relocations ==
 +
 
 +
Because apps are stored at a fixed memory address, they require a relocation table to relocate them during sending and defragmentation.
 +
 
 +
The relocation map consists of a six-byte entry for each location which needs to be updated.
 +
 
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Length
 +
! Contents
 +
|-
 +
| 000h
 +
| 003h
 +
| Hole offset
 +
|-
 +
| 003h
 +
| 003h
 +
| base (2 bits) and relative value to place in hole (22 bits)
 +
|}
 +
 
 +
----
 +
 
 +
'''Relocation Map Format'''
 +
 
 +
The hole offset specifies where in the application code or initial data table an absolute address needs to be updated.
 +
The value to store in the hole is calculated from the base and relative value. The base is 00 for code-segment relative and 10 for data-segment relative. Base values 01 and 11 are reserved.
  
 +
==Example==
  
 
Here is a full demo program demonstrating finding each application, displaying the name, size, version, and copyright information
 
Here is a full demo program demonstrating finding each application, displaying the name, size, version, and copyright information
Line 127: Line 203:
 
;--------------------------------------------------------------------
 
;--------------------------------------------------------------------
 
; Finds all the apps and displays info
 
; Finds all the apps and displays info
 +
_FINDAPPS:
 
ld ix,0
 
ld ix,0
 
add ix,sp
 
add ix,sp
Line 168: Line 245:
 
ld hl,OP3+1
 
ld hl,OP3+1
 
jp cursorImage
 
jp cursorImage
+
 
 
;--------------------------------------------------------------------
 
;--------------------------------------------------------------------
 
ExecuteApp:
 
ExecuteApp:
 
; HL -> name of app (0 terminated)
 
; HL -> name of app (0 terminated)
; An alternative would be to copy to progtoedit and call _NewConext0
 
 
.org cursorImage
 
.org cursorImage
 
ExecuteApp_Start:
 
ExecuteApp_Start:
push hl
+
ld de,progToEdit
call DeletePgrmFromUserMem
+
ld bc,8
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
 
ldir
_: pop hl ; hl -> start of app
+
ld a,cxExtApps
call FindStartOfAppCode ; After this, hl -> start of code for app
+
jp _NewContext
jp (hl)
+
  
 
;----------------------------------------------------------------------------
 
;----------------------------------------------------------------------------
Line 264: Line 305:
 
; Gets the size of an app based from the start of the app
 
; Gets the size of an app based from the start of the app
 
push hl
 
push hl
call _AddNextAppFieldOffset ; move to start of signature
+
call _NextFieldFromType ; move to start of signature
call _AddNextAppFieldOffset ; move to end of signature
+
call _NextFieldFromType ; move to end of signature
 
pop de
 
pop de
 
or a
 
or a
Line 273: Line 314:
 
inc hl ; bypass app size bytes
 
inc hl ; bypass app size bytes
 
ret ; haha, we're probably looking at another app here
 
ret ; haha, we're probably looking at another app here
ExecuteApp_End:
+
ExecuteApp_End:</pre>
</pre>
+
  
 
==Credits and Contribution==
 
==Credits and Contribution==
 
Matt "MateoConLechuga" Waltz
 
Matt "MateoConLechuga" Waltz

Latest revision as of 12:43, 11 September 2020

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 - Disable TI splash screen]
[Bit 1 - App can use OpenLib]

00Eh = Flag

[Bit 0 - Use offset 01Eh for languages]
[Bit 1 - Integrated app]
[Bit 2 - Unknown]
[Bits 3-5 control 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 used in Language apps (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 stored at a fixed memory address, they require a relocation table to relocate them during sending and defragmentation.

The relocation map consists of a six-byte entry for each location which needs to be updated.

Offset Length Contents
000h 003h Hole offset
003h 003h base (2 bits) and relative value to place in hole (22 bits)

Relocation Map Format

The hole offset specifies where in the application code or initial data table an absolute address needs to be updated. The value to store in the hole is calculated from the base and relative value. The base is 00 for code-segment relative and 10 for data-segment relative. Base values 01 and 11 are reserved.

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)
	.org	cursorImage
ExecuteApp_Start:
	ld	de,progToEdit
	ld	bc,8
	ldir
	ld	a,cxExtApps
	jp	_NewContext

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