84PCE:OS:Applications

From WikiTI
Revision as of 06:20, 24 May 2016 by MateoConLechuga (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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. 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)

000h = deleted Flash application (part of the app header)


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.

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 of main header information, followed by perhaps may be a 4 byte checksum

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 + 256 (102503) 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 3 bytes long, so that is where the 043h 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 Data

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 = Copy of the application name (zero padded to be 9 bytes in length)

00Ch = Flag, Bit 0 set -- don't draw the TI splash screen

00Eh = Flag, Bit 0,1

012h = Unknown offset -- 3 bytes

015h = Contains the offset to the initialized data section which should be copied to ram (Can be at most 4kB in size)

018h = Contains the length of the initialized data section

01Bh = Contains the offset to the location to begin execution

01Eh = Unknown

024h = Contains the 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


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
	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	_AddNextAppFieldOffset	; move to start of signature
	call	_AddNextAppFieldOffset	; 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