NB: This documentation refers to software that is currently in development - some things will change!

TI Application Development in Brass

Brass can be used to develop applications for the TI-83+ (and compatible) and TI-73 calculators. This document should help you get started.

Setting up the SDK

Brass does not sign applications itself - it delegates the job to the Wappsign utility supplied as part of the TI-83 Plus SDK. You must have the SDK installed, therefore, to sign applications.

You need to run Wappsign. It should be listed somewhere in the TI-83 Plus Flash Debugger start menu entry, or in the \Utils subdirectory of the Flash Debugger's installation folder. For signing to work, the Wappsign application needs to know where your key file resides. Click the [...] button next to the 'Key File' box, then browse for the 0104.key file. Click 'Yes' on the 'This directory is not in your search path. Add it now?' dialog box. Tick the 'Save Settings on Exit' box, then click 'Close'.

Simple one-page application

Applications are a bit of a pain in comparison to the usual RAM programs, and developing them is not as forgiving. Brass, however, tries to make things a bit easier for you.

One thing you must do is define the various pages that your application uses. Let's start with a simple, single-page application.

Each page is 16KB in size, and we know that they start at address $4000. We also know that the first page, page 0, has 128 bytes of header information at the start of it. The simplest application (which can be used as a template), therefore, is:

.binarymode ti8xapp                 ; TI-83+ Application

.inclabels "ti8x.lbl"               ; Label file containing equates

.deflong bjump(label)               ; Jump macro
    call BRT_JUMP0
    .dw label
.enddeflong

.deflong bcall(label)               ; Call macro
    rst rBR_CALL
    .dw label
.enddeflong

.defpage 0, 16*1024, $4000          ; Page 0 definition

.page 0                             ; Start page 0
                                    ; ← header is added in here for us
    .block 128                      ; Advance 128 bytes for header
    
    bjump(_JForceCmdNoChar)         ; Exit

If you now assemble that program you should end up with two files - a .hex file and a .8xk file. The .hex file is the assembler output - this can be used in the Flash Debugger. The .8xk file is the signed application, and can be sent to a calculator or run in a 3rd-party emulator.

If you run this application, not an awful lot happens - the application just exits. Let's make it do something a bit more creative and display some text in true "Hello World" tradition. New code is in black text.

.binarymode ti8xapp                 ; TI-83+ Application

.variablename "App Demo"            ; Application name (shown in 'Apps' menu)

.inclabels "ti8x.lbl"               ; Label file containing equates

.deflong bjump(label)               ; Jump macro
    call BRT_JUMP0
    .dw label
.enddeflong

.deflong bcall(label)               ; Call macro
    rst rBR_CALL
    .dw label
.enddeflong

.defpage 0, 16*1024, $4000          ; Page 0 definition

.page 0                             ; Start page 0
                                    ; ← header is added in here for us
    .block 128                      ; Advance 128 bytes for header
		
        bcall(_ClrLCDFull)          ; Clear the screen
    
        xor a                       ; Reset the -
        ld (curCol),a               ; cursor column and the -
        ld (curRow),a               ; cursor row.

        ld hl,TextString            ; Copy from...
        ld de,saveSScreen           ; Copy to...

    -   ld a,(hl)                   ; Copy the string to RAM
        ld (de),a
        inc hl
        inc de
        or a
        jr nz,{-}
        
        ld hl,saveSScreen
        bcall(_putS)                ; Display the string
        
        bcall(_getKey)              ; Wait for a key
        
        bjump(_JForceCmdNoChar)     ; Exit
		
    TextString
        .asc "This simple app."
        .asc "just displays a "
        .asc "bit of text on  "
        .asc "your calculator "
        .asc "screen.",0

(This is a guide to setting up Brass for application development, not a Z80 assembly tutorial - I assume you can follow what I'm doing!)

Multiple Page Applications

Sometimes 16KB is not enough, and you need to expand to a multipage application. Brass, being a multipage assembler, can help you with this. Thankfully, you only need to change two things:

  1. Add a new definition for each page you add.
  2. Add a branch table for off-page calls.
The purpose and structure of the branch table is explained in the SDK documentation.

The .branch directive adds a branch table item and uses the style demonstrated in the SDK documentation - it creates a new label name by appending an underscore to the 'real' name of the label you are adding an entry for. In the following example the function OffPageCall resides on page 1, so a branch table entry is created which in turn adds the label _OffPageCall for use with the bcall() macro.

.binarymode ti8xapp                 ; TI-83+ Application

.variablename "App Demo"            ; Application name (shown in 'Apps' menu)

.inclabels "ti8x.lbl"               ; Label file containing equates

.deflong bjump(label)               ; Jump macro
    call BRT_JUMP0
    .dw label
.enddeflong

.deflong bcall(label)               ; Call macro
    rst rBR_CALL
    .dw label
.enddeflong

.defpage 0, 16*1024, $4000          ; Page 0 definition
.defpage 1, 16*1024, $4000          ; Page 1 definition

.page 0                             ; Start page 0
                                    ; ← header is added in here for us.
    .block 128                      ; Advance 128 bytes for header.   
        
        jp Run                      ; Jump past the branch table
        
        .branch OffPageCall         ; Add a branch table item
        
    Run
        
        bcall(_ClrLCDFull)          ; Clear the screen
    
        xor a                       ; Reset the -
        ld (curCol),a               ; cursor column and the -
        ld (curRow),a               ; cursor row.

        ld hl,TextString            ; Copy from...
        ld de,saveSScreen           ; Copy to...

    -   ld a,(hl)                   ; Copy the string to RAM
        ld (de),a
        inc hl
        inc de
        or a
        jr nz,{-}
        
        ld hl,saveSScreen
        bcall(_putS)                ; Display the string
        
        bcall(_getKey)              ; Wait for a key
        
        bcall(_OffPageCall)         ; Call the off-page function
                                    ; (Note the _underscore!)
        
        bcall(_getKey)              ; Wait for a key (again)
        
        bjump(_JForceCmdNoChar)     ; Exit

    TextString
        .asc "This simple app."
        .asc "just displays a "
        .asc "bit of text on  "
        .asc "your calculator "
        .asc "screen.",0
        
.page 1

    OffPageCall
        
        xor a
        ld (curCol),a
        ld a,5
        ld (curRow),a
        
        ld hl,TextString2           ; Copy from...
        ld de,saveSScreen           ; Copy to...
        
    -   ld a,(hl)                   ; Copy the string to RAM
        ld (de),a
        inc hl
        inc de
        or a
        jr nz,{-}
        
        ld hl,saveSScreen
        bcall(_putS)                ; Display the string
        
        ret                         ; Return
    
    TextString2
        .asc "This text is on "
        .asc "page 1!",0