siraben / ti84-forth

A Forth implementation for the TI-84+ calculator.
GNU General Public License v3.0
89 stars 4 forks source link
assembly calculator forth ti84 z80

Forth implementation for the TI-84+ calculator

Defining DOUBLE

Features

Getting the interpreter

Download the latest binary from the Releases page or get the bleeding edge output from the GitHub Actions CI.

The Real Thing

Flash forth.8xp to your calculator. Make sure there's enough space and that you have backed up your calculator! An easy way to back up RAM contents is by creating a group, refer to the manual on how to do this.

Why TI-84+?

This is a calculator that is more or less ubiquitous among high school and university students throughout the world. It's not going extinct anytime soon (except perhaps to newer models such as the TI-84 CE). But let's face it. TI-BASIC is not a nice language; it's slow and suffers from lack of low-level bindings. There's no REPL. We want a language that gives the programmer the full power of the calculator—treating it as the computer it is. In fact, people already do, by writing assembly programs, but assembly has its share of disadvantages.

Why Forth?

Assembly is painful to program in. Programs crash at the slightest hint of error. Development is a slow process, and you have to keep reinventing the wheel with each program.

Wouldn't it be great to have a programming language on the TI-84+ that's much faster than TI-BASIC but easier to understand and as low level as assembly? Forth is just that. (Read Starting FORTH for an excellent introduction to Forth). It's low level, it's simple, but also easy to type, especially when you're on a calculator with a non-QWERTY keyboard. It is a very powerful language, allowing you to do things like change the syntax of the language itself. IF, WHILE, CONSTANT etc. statements are all implemented in Forth! Think of it as an untyped C with a REPL and the power of Lisp macros.

It's also easy to implement incrementally through continuous testing. In fact, once the base REPL was implemented, most of the programming and testing happened on the calculator itself!

Building

Nix

nix build

Mac/Linux

Copy forth.asm into the cloned folder. Then run:

./spasm forth.asm forth.8xp

Emulated

There are many emulators out there, one that doesn't require installation is jsTIfied. Read the website's details for more information. You'll need to obtain a ROM image as well, which I can't provide here, but a simple web search might help.

Using the Interpreter

Run the program with Asm(prgmFORTH), hit 2nd then ALPHA to enter alpha lock mode, and now you can type the characters from A-Z. Here are a couple of things to keep in mind.

If you want to see the keymap, find the label key_table in forth.asm. This table maps the keys received by KEY to the appropriate character.

Typing ASCII Characters

See the 2nd or ALPHA key combos (in blue on the calculator) for information on how to type the following characters: []{}"?:.

Character Key Sequence
; 2nd .
! 2nd PRGM
@ 2nd APPS
= 2nd MATH
' 2nd +
< 2nd X,T,Θ,n
> 2nd STAT
\ 2nd ÷
_ 2nd VARS

Exiting the Interpreter

Type BYE and hit ENTER.

Here is the more concise "Loading Forth Programs onto the Calculator" section:

Loading Forth Programs onto the Calculator

Use the provided fmake.py script to convert Forth source files to the TI-84+ executable format.

Run the script to generate the assembly file:

python fmake.py hello.fs

To also assemble it to a .8xp executable, add the --assemble flag:

python fmake.py hello.fs --assemble

Transfer hello.8xp to your calculator using TI Connect CE and load it into the interpreter by running LOAD HELLO in the Forth REPL on your calculator.

Example Programs

See programs/ for program samples, including practical ones.

Available Words

EXIT DUP + - AND OR XOR << >> INVERT DROP SWAP OVER ROT -ROT 2DROP
2DUP 2SWAP 1+ 1- 2+ 2- >R R> R@ 2>R 2R> RDROP 2RDROP LIT LITSTR S" .Q
TELL STRLEN STRCHR !  @ +!  -!  C!  C@ C@C!  CMOVE EXECUTE BASE PREC
STATE LATEST SP0 [ ] ?SE HERE DOCOL BUF BUFSZ WBUFP WBUF WBUFSZ RP0 H0
F_IMMED F_HIDDEN F_LENMASK SCR ABS PLOTSS ' , C, SP@ SP!  RP@ RP!
BRANCH 0BRANCH ?DUP = <> >= <= < > 0= KEY KEYC EMIT T.  ?  AKEY
TO_ASCII * /MOD SQRT FRAND F.  FREAD F* FSQUARE F= FDUP FDROP FSWAP F+
F/ FRCI F- FSQRT MD5 D/MOD UM* D+ M+ DS SPACE CR AT-XY PUTS PUTLN GETS
GETC UNGETC WORD ?IMMED IMMED >NFA >CFA STR= FIND WB USED SIMG LIMG
>DFA CREATE DOCOL_H : ; (DOES>) DOES> PAGE HIDDEN ?HIDDEN MOD / NEGATE
TRUE FALSE NOT LITERAL NIP TUCK ID.  HIDE IF THEN ELSE BEGIN UNTIL
AGAIN WHILE REPEAT CHAR (COMP) CONST ALLOT CELLS RECURSE VAR DO LOOP
+LOOP FORGET '0' '9' WITHIN NUM?  CFA> PICK U.  UWIDTH SPACES U.R U.
.  DEPTH .S HEX DEC SEE WORDS CASE OF ENDOF ENDCASE I J CSCR CBLK FBLK
RUN LOAD SMIT PLOT WR PN BYE STAR

Note that floating point routines are commented out by default to save space.

Screenshots

Combine words in powerful, practical ways

Combine low-level memory words with drawing words and user input words to create an arrow-key scrollable screen for viewing RAM memory. See the 20 (or less) lines of code at programs/memview.fs.

What forth.asm looks like loaded into RAM

TI-84+ inside

key-prog program

Load programs

Simple unfinished modal text editor with a scrollable screen.

Unfinished text editor

Design Notes

Use of Macros

Judicious use of macros has greatly improved the readability of the code. This was directly inspired by the jonesforth implementation (see Reading List).

Register Allocation

One notable feature of this Forth is the use of a register to keep track of the top element in the stack.

Z80 Register Forth VM Register
DE Instruction pointer (IP)
HL Working register (W)
BC Top of stack (TOS)
IX Return stack pointer (RSP)
SP Parameter stack pointer (PSP)

Reading List

Documentation can vary from very well-documented to resorting to having to read the source code of spasm-ng to figure out how #macro worked. See examples such as defcode and defword. I couldn't make defconst or defvar, however, but this was fixed by writing it out manually.

To be Implemented

Current Limitations