-= THE TI-82/83(+) UNIFICATION FAQ =-

by Guillaume Hoffmann
revision 9: 05/05/2005
grammar fixes: 04/13/2009 by TI-Freakware

I Introduction
II The actual FAQ

1. Which shell should I program for on each calculator?
2. Are there already existing headers to do so, or will I have to do it all by myself ?
3. Do all these calculators have the same saferams ?
4. How do I manage ROM Calls on these different calculators ?
5. How can I use the free RAM ?
6. What about other z80-based devices ?

III To do / Questions without answser
IV Contact/thanks
V History

I Introduction:

The purpose of this FAQ is to help programmers who program only for TI-82, TI-83 or TI-83+ to program for these 3 calculators at the same time.

When ION was released, making easy the development on both TI-83 and TI-83+, it was the first time people could almost transparently program for two (quite) different calculator models. But unfortunately nothing has evolved since then.

You may be wondering why I don't include the TI-85 and TI-86 in this FAQ. The answer is : it's only a matter of time. If you really want the clues to do it, just get "Phoenix" by Patrick Davidson at http://pad.calc.org, and see how the author manages to build a program for every TI-z80 calc with almost the same source code.

Last, you may have already noticed that English is not my mother language, so you can e-mail me to report spell and grammar errors :)


II The actual FAQ:

1. Which shell should I program for on each calc?

Remarks :
* the way I use the word "shell" is sometimes abusive (in example, Venus is rather a plug-in than a shell)
* I don't always use the right names for each built-in functions, I prefer to use names that give you an immediate idea of what it does. And sometimes functions to which I give the same name are a little different :)
* I don't mention outdated shells

The choice of the shell depends on several points:

1) amount of RAM it leaves once loaded (FBLOI: free bytes left once installed)
2) built-in functions
3) stability
4) compatibility with other shells

Explanation:

1) Very important because the user will be more comfortable when they can put more (or bigger) programs on their calc. It may be important also if the programmer wants to make a full use of the calculator's memory.

2) It can be good and bad at the same time, because if a program uses a lot of shell functions, it will certainly be bigger once ported to another calc, because the shell will be different and may not have all the functions used; on the other hand, if a there are many shell functions that aren't used by a majority of programs, there functions are useless and still take your calc's precious memory. The best compromise is a shell that has only really useful functions.

3) Most of the shells are stable, but some of them are no longer maintained or still under development. It is seldom a real issue.

4) It can be useful if you don't want to force the user to forsake their beloved programs that work with an older shell. But, obviously, this can interfere with the 1st point, beware!

So the most important points you should look at are the first two ones. I'm going to make my own research on this topic :

On TI-82 :

The choice is hard, because, to me, there isn't really a "best ti-82 shell", they all have drawbacks.


CrASH
CrASH19006 ACE
SNG
FBLOI
27700 25700 26930
Built-in routines
FastCopy, Random, Exit2TIOS, CP_HL_BC
CrASH ones + Pause, Fill (hl) with a, HL_DECI, DirectKey...
ACE ones + Greyscale, Beep, Mul_HL_BC, HL_HEX...
For which ROMs ? all but 19.006
19.006
All known ROMs
Comment You have to compile two different versions, one for CrASH, another one for CrASH19006.
Beta, no longer maintained.
Uses TEXT_MEM2. Has an inner 2 kB buffer.
Has "emulators" to run CRASH, ASH, ACE and ION programs.

My choice : CrASH/CrASH19006

Remark : if you don't use any ROM call and no link routine, you can compile a single program for any TI-82 ROM versions, than can be run with CrASH and CrASH19006. For the link issue, you can find more info here (in French).

On TI-83 :


ION
Venus
FBLOI 25800
26900
Built-in routines
FastCopy, Random, Putsprite, Putlargesprite, Getpixel, Detectprogram, Unpackdata
FastCopy, Random
Comments
Allows to lauch program directly from the TI-OS. It is just a single program that you can sent and delete at wish. Can run ION and SOS programs with an external module.

My choice : Venus

On TI-83+ :


ION
MirageOS
FBLOI 22800
24300
Built-in routines
FastCopy, Random, Putsprite, Putlargesprite, Getpixel, Detectprogram, Unpackdata
ION ones + lots
Comments

It's a Flash APP, so it leaves all RAM free.
Handles ION programs.

My choice : I make ION programs and I use MirageOS

I've chosen ION because it has fewer features, so I prevent myself from using extra features of MirageOS that will be hard to let down on other calcs. Plus, a ION program can be run with MirageOS, while the contrary is impossible.

There is also the possibility to make flash APPs, but you won't be able to use self-modifying code, and you'll have to create APP vars  to store things like highscore, saves, etc. Plus, your programs must fit in one or several 16 kB Flash APPS, that means that a 5 kB program will use a whole 16 kB Flash APP, and that a 24 kB program will use two 16 kB Flash Apps (that you will have to link together...).

2. Are there already headers to do so, or will I have to do it all by myself?

It depends on which compiler you use.

The most widespread one is TASM. It works under DOS (thus Windows). You can also launch TASM under Linux with DOSEMU or WINE. But you have to know that it is a shareware, it is not free, though propably noone and nothing will prevent you from using it for years, like almost the whole ti-community does :)

The less known one is TPASM. It works under Unix (and Linux). It's under the GNU/GPL. TPASM requires a source code syntax that is a little different from TASM's, i.e. the MACROs are defined differently, you must use "db", "dw", "ds", "org", etc. instead of ".db", ".dw", ".ds", .org"... Another important thing is that TPASM is case sensitive, including for the labels, while TASM isn't.

In case you use TASM, the header you may use is "dwedit.inc", by Dan "Dwedit" Weiss. You can find it at http://home.comcast.net/~alanweiss3/dwedit/ti/. With this header, you will be able to program for TI-82, TI-83(+) and even TI-73 ! You will also be able to make Flash Apps for ti-83+. It's really a huge header, and it handles almost all known shells.

If you use TPASM, I've made a header called "vion.inc". You can find it at http://etrange.paxl.org/. This header handles CrASH and CrASH19006 for the TI-82, Venus for the Ti-83 and ION for the Ti-83+. That's all! It is just my own little header, but then you can add what you want for yourself.

3. Do all these calculators have the same saferams ?

Saferams are really useful, but sometimes you can't do what you want with them.

The most useful one is the APD Buffer, which is 768 bytes big. On TI-83(+) there's no problem, they are only used if the calc shuts down after a few minutes of inactivity (Auto Power Down) so it won't happen in your programs (unless you use the rom call _getkey, that is NOT recommended !)

But on TI-82 it's a little more difficult; actually it depends on the shell you are using. I don't really know how it works for ACE and SNG... CrASH(19006) has a disturbing feature ; it allows to install an interrupt routine in the APD_BUF, that stays even when another program is launched... So, as I don't care about what the others' interrupt routines will do, I merely disable them as I start my program, like this (replace the # by a space for TPASM) :

#IFDEF TI82
    im 1 ; tells to the z80 processor to stop executing "custom interrupt", and to execute the "normal interrupt" instead
    xor a
    ld (INT_STATE),a ; tells CrASH that there is no more interrupt routine installed (not really useful I think)
#ENDIF

Now you have the whole APD_BUF for you alone.

There is another useful saferam: TXT_BUF (128 bytes big). This one is usable on TI-82,83(+) without problem, just remember to reset it before leaving your program, if you don't want remaining weird characters on the TI-OS screen.

And last, the OPs (the area where are stored the Floating Points values) that is 66 bytes big. You can use it as long as you don't use any rom call concerning FP operations (that is a wise decision because they are sluggish, unless you really need to do FP maths).

We also have the PlotsScreen area (768 bytes) on every calc model. It is almost always used as a buffer for the display, but you can use it as a saferam.

There are other saferams, but for compatibility's sake, we can't use them :

* StatRam (531 bytes) is on TI-83(+) but not on TI-82. Moreover, on TI-83+, MirageOS has its own interrupt that uses the first bytes of StatRam, as says the doc :

( By default, there will be an interrupt running during your program. This interrupt is located in the StatRam location. If you wish to use StatRam for variable storage, you must disable interrupts or set IM 1 before doing so.

So, for the TI-83+ version of your program, if you really want to use StatRam, put im 1 at the beginning of your program, to be sure it's wot mess everything up.

* On TI-83+ there are appBackupScreen (768 bytes) and tempSwapArea (323 bytes), but they aren't on TI-82/83 as they are related to Flash RAM.

* On TI-83(+) we have imathptrs (10 bytes), I don't know what it's for, but as it isn't on TI-82 we won't use it.

* The TI-83(+) have a ram place called cmdShadow, that is 128 bytes big. It is not free when you use ION or MirageOS, but with Venus there's no problem. This area is called TEXT_MEM2 on TI-82, and gets reseted each time you call the CR_HAND routine under CrASH (but you shouldn't use CR_HAND = _getkey).

Summary table :

Saferam name
APD_BUF (savesscreen)
TEXT_MEM (textshadow)
OPs
cmdShadow / TEXT_MEM2
StatRam imathptrs
appBackupScreen
tempSwapArea
Size 768
128
66
128
531 10
768
323
TI-82 status, address
Available (with CrASH, after disabling interrupts)
$8228
Available
$808F
Available
$8028
Available (reseted when you call CR_HAND; Non Available with ACE)
$8BDF
Non Available (doesn't exist)
TI-83 status, address
Available
$8265
Available
$80C9
Available
$8039
Available (with Venus only)
$9157
Available
$858F
Available
$8094
Non Available (doesn't exist)
TI-83+ status, address
Available
$86EC
Available
$8508
Available
$8478
Non Available (used by shells)
$966E
Available (disable interrupts)
$8A3A
Available
$84D3
Available
$9872
Available (unless during Flash ROM loading)
$82A5
Use it ?
Yes
Yes
Yes
No
No No
No
No

We can use 3 saferams, but look at the grey cells : the smallest among them is TEXT_MEM2 on TI-82 (and cmdShadow on TI-83), so in the source code of your programs you can refer to these 3 different saferam as a single one that is 128 bytes big like this :

#IFDEF TI82
 mysaferam=$8BDF
#ENDIF

#IFDEF TI83
 mysaferam=$9157
#ENDIF

#IFDEF TI83P
 mysaferam=$9872
#ENDIF

Thus, later in your program, you will be able to use these 128 bytes to store temporary data :

ship_x = mysaferam
ship_y = ship_x+1
life = ship_y+1
...

Now we can say that we have 4 common saferams on TI-82, TI-83 and TI-83+ ! THIS is useful !

4. How do I manage ROM Calls on these different calcs ?

First of all, read carefully the following sentence, and copy it a hundred times on a sheet of paper :

I SHALL NOT USE ROM CALLS

You're certainly wondering why. "They're handy and they make my programs smaller!", I hear you say. Sure. It is also true that, since we program in ASM, we are used to heavily depend on the hardware our programs will run on, so for certain things very hardware-related (i.e. for all that concerns the VAT) we just can't avoid using ROM calls.
But from an "unification" point of view, you must remind that the more your program is machine-independent, the better it is.

One thing for sure is that you won't always find the same ROM Calls on different calc models (and I'm not yet considering the possibility to port your program to other z80-based systems). It will not really kill the porting process, but I'm sure that the amount of time you want to give for TI-programming is not so big. So, take the good way since the beginning, and use ROM call as less as possible.

Plus, you will see further in this part that dealing with bcall, icall, bjp and ijp are a pain...

Moreover, ROM calls on the TI-8X+ series are slow, this is because the bcall thingy looks for the right ROM page before calling the routine. So it is also a speed issue.

Oh, I was about to forget mention this reason ! :)

Now, here are some explanations if you really want or have to use ROM calls :

If you already program for TI-83 and TI-83+, you are already used to "bcall" instead of "call" for calling ROM Calls. This is a command that is equated by the compiler, differently in function of the calc :
* for the TI-83 is is replaced by a mere "call"
* for the TI-83+ it is replaced by a slow code that handles different rom pages to find the ROM Call (don't ask me how the TI-83+ memory works...)

But when you program also for the TI-82 you have to take in account 2 categories of TI-82 ROM Calls : those that you can directly call with a mere "call", and those you can't (that's where the shell is useful).

Here is a table to visualise how it works (the ???? address is the address of the routine used by CrASH(19006) to handle ROM Calls) :

Command
bcall xxxx
icall xxxx
bjp xxxx
ijp xxxx
TI-82 transcription
call ????
dw xxxx
call xxxx
bcall xxxx
ret
jp xxxx
TI-83 transcription call xxxx
call xxxx
jp xxxx
jp xxxx
TI-83+ transcription rst 28h
dw xxxx
bcall xxxx
bcall xxxx
ret
bjp xxxx

Hopefully, the ROM Calls that require icall aren't too numerous. (reminder : this is for CrASH(19006) programming) :

_ldhlind ( LD_HL_MHL )
_cphlde (CP_HL_DE )
_divhlby10 ( UNPACK_HL )
_divhlbya ( DIV_HL_A )
_getcsc ( GET_KEY )
_lcdbusy ( DISP_DELAY )

The faster you'll memorize them, the fewer bugs you'll experience in your developpements, because confusing an icall/ijp with a bcall/bjp always leads to a crash on TI-82.

Replacing ROM calls

Here is an explanation of how I do to avoid using ROM calls.

For the following rom calls, I merely paste their code into my programs (it's small) :

_ldhlind
_cphlde
_divhlby10
_divhlbya
_lcdbusy

For _clrlcdf, I first clear the graph buffer and then I update the screen with a FastCopy routine. Quite dirty, but for now I realize that I don't need speed when I use _clrlcdf.
When I need speed for a _clrlcdf routine, I'll make one based on the FastCopy.

Now the most controversial part :

_puts (and its derivates) : I use only small fonts, so I don't need these :)

_vputs (and its derivates) : here comes the one that can make your programs noticeably bigger... I think the best replacement for this routine is the one made by Dan "Dwedit" Weiss for Bubble Bobble 85. This routine draws the most useful characters jsut like the _vputs routine and it's 334 bytes big. I've also made a 4x4 version or this routine that is 220 bytes big. There are also (not as good) routines like it at http://void.ticalc.org, just look at the file font.h or into the program TxtView.

Using a replacement for _vputs also allows to develop TI-85 versions of your programs, because on this calc you can't write in the graph buffer in small fonts. It also allows to have a personnalised font, and some extra characters you may want to insert that are not in TI's "ASCII".

Other explanations will come ... Feel free to send to me your remarks and suggestiosn about this.

*to do : _getcsc replacement*

5. How do I use the free RAM ?

Sometime, you need a BIG temporary buffer for your games. You can  put it inside your program, but it would be a waste because it will take space even if your program isn't running. So the best solution is to use the free RAM of your calc.

On TI-83 and TI-83+, it's easy to do so. Put these equates in the header you're using (if they aren't already there) :

#IFDEF TI83
FREE_MEM_START = $930D
FREE_MEM_END = $9311
_enoughmem = 443Ah
#ENDIF

#IFDEF TI83P
FREE_MEM_START = $9824
FREE_MEM_END = $9828
_enoughmem = 42FDh
#ENDIF


_enoughmem is a rom call that compares the value given in HL with the amount of free RAM. After calling it, the carry flag is set if there is not enough free RAM. I think it is not available on TI-82.
Let's say you need 4000 bytes. At the beginning of your program, put :

ld hl,4000
bcall _enoughmem
ret c

Thus, the program won't start if there is not enough free mem (you may want to display a "not enough free mem" message in this case).
Later, to access this "buffer", you'll have to do :

ld hl,(FREE_MEM_START) ; now HL has the address of the buffer

On TI-82 :

Marc Plouhinec, the author of the TI-82 shell SNG v 1.0, has included these macros in the file SNG.inc :

;Creates a buffer if there is enough memory, leaves if not (ret)

#Define CREATEBUFFERANDTESTMEM1(Size,BufferAddress)
ROM_CALL(DEL_TMP)
LD HL,Size
ROM_CALL(MEM_FREE)
JR NC,EnoughMem
ROM_CALL(CREATE_TMP)
RET
EnoughMem:
LD HL,Sizee
LD DE,BufferAddress
ROM_CALL(INSERT_MEM)
ROM_CALL(CREATE_TMP)

;Creates a buffer if there is enough memory, jumps at the label NotEnoughMem else.

#Define CREATEBUFFERANDTESTMEM2(Size,BufferAddress,NotEnoughMem)
ROM_CALL(DEL_TMP)
LD HL,Size
ROM_CALL(MEM_FREE)
JR NC,EnoughMem
ROM_CALL(CREATE_TMP)
JR NotEnoughMem
EnoughMem:
LD HL,Size
LD DE,BufferAddress
ROM_CALL(INSERT_MEM)
ROM_CALL(CREATE_TMP)

;Destroys the buffer
#Define DELBUFFER(Size, BufferAddress)
ROM_CALL(DEL_TMP)
LD DE,Size
LD HL,BufferAddress
ROM_CALL(DEL_MEM)
ROM_CALL(CREATE_TMP)

When you "call a macro" to create a temporary buffer, you have to specify the address of the buffer. A solution that works well is simply to choose the adress of the byte right after the end of the current program. You merely need to define a label at the very end of your program, and use this label as the address of the temporary buffer. The romcalls INSERT_MEM and CREATE_TMP take care of moving the other programs, so in theory you can choose any adress, but choosing the previous solution works fine.

CoBB says : "These macros work only with those shells that leave the VAT consistent with the memory. That means no CrASH." So for the moment you'd better stick to SNG 1.0 if you want to use free ram on TI-82.

CoBB also has an easy way to make this "83(+) compatible", by introducing the 2 FREE_MEM_START and FREE_MEM_END variables :

; These equates are in the OPs, but they could be anywhere (only 4 bytes needed)
FREE_MEM_START = $8028
FREE_MEM_END = $802A

ROM_CALL(DEL_TMP)
LD HL,Size
ROM_CALL(MEM_FREE)
JR NC,EnoughMem
ROM_CALL(CREATE_TMP)
JR NotEnoughMem
EnoughMem:
LD HL,Size
LD DE,BufferAddress
LD (FREE_MEM_START),DE
ROM_CALL(INSERT_MEM)
ROM_CALL(CREATE_TMP)
LD HL,BufferAddress+Size; These are constant anyway
LD (FREE_MEM_END),HL

6. What about other z80-based devices ?

Sinclair Computers

(not_yet_implemented)

Game Boy

Learning that the GameBoy has a z80 processor is quite mouthwatering, but the bad news is that it is a modified version. The GB processor has :

* No IX, IY and shadow registers.
* No input/output operations (so no in/out opcodes).
* HALT is interrupted even when interrupts are disabled.

And several opcodes are changed, including the following :

DJNZ offset
LD (word),HL
LD HL,(word)
LD (word),A
LD A,(word)
EX HL,(SP)
EX DE,HL

This text file explains more deeply the differences between the GB's processor and a regular z80 processor.

So, you get the idea, it is almost impossible to have similar source codes that run on both GB and TI z80.

III To do/Questions without answer

How do I replace the rom call _getcsc ?
How do I handle external programs ?
Is a TI-z80 program easily portable on z80-based Sinclair computers ?

IV Contact/thanks

If you have any suggestion, comment or question about this FAQ, contact me!

E-mail : guillaume.h (a) ifrance dot com

Webpages: http://etrange.paxl.org/, TIFT

Thanks to (in no particular order):

CoBB
Kozak
Pat Fagan (who made the GB's z80 comparsion)
pacHa

and anyone acting for the ti-community :)

V History

revision 9 : 05/05/2005
Some minor corrections.

revision 8 : 28/10/2004
Added the info about using the free RAM on TI82 with SNG. BIG thanks to Marc Plouhinec, pacHa and CoBB for this.

revision 7 : 01/07/2004
Complete the "don't use rom calls" stuff with _vputs replacement.
Used neutral pronouns ;)

revision 6 : 06/06/2004
Added the "don't use rom calls" and Game Boy stuff.

revision 5 : 01/03/2004
Added the incomplete "free RAM" part.

revision 4 : 28/10/2003
Added several precisions

revision 3 : 07/10/2003
Added the saferam addresses.

revision 2 : 06/10/2003
Added the icall/bcall/ijp/bjp part.

revision 1 : 05/10/2003
I realised that cmdShadow and TEXT_MEM2 were the same thing...
Mentionned the PlotsScreen in the saferam part.
Corrected several things

revision 0 : 04/10/2003