Text Display

z80 » Intermediate

Text is an important part in any program, used to communicate with the user. There are three types of text you can use on the TI86. Two of them are built into the calculator. The third is called User Font. The two types of built in font are the regular 5x7 pixel characters (big size font) and the variable width (menu size font) 6 pixel high font. Different routines are used for each size font.

Big Font

Both fonts use cursor coordinates to put text at various locations, like Outpt(row,column,string) in TI-BASIC. But in asm, you can't use arguments like that; you've got to store the row number in one memory designated area and the column number in another designated area. Before you put a character (letter) on the screen, you have to load the coordinates of where you want the string to be printed at into those memory locations, or else the letters will be printed at the current values stored there. These memory addresses, along with all other ROM call addresses and cursor coordinate memory addresses are all defined in ti86asm.inc which should just about always be included in your source files.
_curRow		=$c00f
_curCol		=$c010

The coordinates are set up according to the following representation of the TI86's screen. The top left would be Row 0, Column 0. The bottom left would be Row 7, Column 0. Each big character is the same width across (5 pixels and then a pixel space between characters).

(0,0) (20,0)
(0,7) (20,7)

After you've loaded the cursor position into the above memory coordinates you load the letter, character, you want displayed into a. Then you can call the text display routine of your choice for displaying a letter. There are two:

_PutMap

Description Prints one letter at the cursor position and does not advance the cursor.
Inputs A is the character to be printed.
Destroys none
Output A is printed on the screen in its ASCII equivolent and the cursor position is still the same.

_PutC

Description Prints one letter at the cursor position and advances the cursor.
Inputs A is the character to be printed.
Destroys none
Output A is printed on the screen in its ASCII equivolent and moves cursor position one to the right. If this is past the end of the row, the cursor coordinates are advanced to the start of the next row down. The screen is scrolled up if needed.

Here's two examples of printing text using each of the above ROM calls. The first prints the letter M on row 4, column 8 and does not advance the cursor position. The second prints the question mark (? or Lquestion) and on row 2, column 20 and advances the cursor position to row 3, column 0 because that was the end of the line.

	ld a,'M'		;character to print
	ld hl,(256*8)+4		;row 4, col 8
	ld (_curRow),hl		;loads l into _curRow
				; and h into _curCol
				; (most significant byte
				; is stored first in mem)
	jp _putmap		;print it and return
	ld a,Lquestion		;character to print
				;this is the equate
				; defined in ti86asm.inc
	ld hl,(256*20)+2	;row 2, col 20
	ld (_curRow),hl		;loads l into _curRow
				; and h into _curCol
				; (most significant byte
				; is stored first in mem)
	jp _putc		;print it and return

Now that you know how to put a single character on the screen, it's time to move on to bunches of them at once. A bunch of letters or characters, one right after the other, is called a string of characters. There are two types of strings used with the TI86: zero-terminated and length-indexed.

Zero-terminated, or sometimes called null-terminated, strings are a bunch of letters and then a $00 to tell the routine to stop displaying the letters. $00 was used because the character $00 is not used often.

Length-indexed strings have a byte in front of all the letters telling the routine how many letters follow. This leading byte value has a limit of 255 because it's 8 bits, so the string can only be up to 255 letters. The zero-terminated strings can be as long as you want them. I prefer to use zero-terminated strings becuase I hate counting how many letters are in the string. Check out the Assembler Directives section to see the different ways you can use .db and .text. Here are some examples of both types of strings.

	.db "Stupid",0		;zero-terminated
	.db "La..La..La..",0	;zero-terminated
	.text "La..La..La.."	;zero-terminated
	.db 10,"Mea Culpa."	;length-indexed
	.db 5,"xStat"		;length-indexed
	.db 4,'a',Lcomma,"zz"	;length-indexed

There are two routines, _PutS and _PutPS, especially for zero-terminated strings and length-indexed strings respectfully.

_PutS

Description Prints a string of characters until it encounters $00.
Inputs hl holds the address of the string to print.
Destroys hl holds address of byte after $00.
Output hl string is printed on the screen in its ASCII equivolent. The cursor coordinates are updated to the position after the last character of the string that was displayed. The carry flag is set if the entire string was able to be displayed, or reset if the string ran off the edge of the screen. The string does not disappear off the edge of the screen. It is simply wrapped around to the beginning of the next line. The screen is scrolled up if needed.

_PutPS

Description Prints a string of characters whose length is determined by the leading byte.
Inputs hl holds the address of the string to print.
Destroys hl holds address of byte after $00. A holds the last character printed. B is $00.
Output hl string is printed on the screen in its ASCII equivolent. The cursor coordinates are updated to the position after the last character of the string that was displayed. The carry flag is set if the entire string was able to be displayed, or reset if the string ran off the edge of the screen. The string does not disappear off the edge of the screen. It is simply wrapped around to the beginning of the next line. The screen is scrolled up if needed.

Here's two examples of printing text using each of the above ROM calls. The first uses _PutS to print the string "This is stupid!" on row 0, column 7. The second uses _PutPS to put the string "Stupid" on row 7, column 4.

	ld hl,(256*7)+0		;row 0, col 7
	ld (_curRow),hl		;loads l into _curRow
				; and h into _curCol
	ld hl,stupid_string	;string to print
	jp _puts		;print it and return
stupid_string:	.db "This is stupid!",0
				;zero terminated
	ld hl,stupid_string	;string to print
	ld bc,(256*7)+0		;row 0, col 7
	ld (_curRow),bc		;loads c into _curRow
				; and b into _curCol
	jp _putps		;print it and return
stupid_string:	.db 6,"Stupid"	;length indexed

Variable Width Font

Variable width font, also called menu size font, functions much the same as the big font. You load the coordinates and call the routines. Like the big font, menu size font has its own routines for displaying. You load the coordinates into the following addresses defined in ti86asm.inc which should just about always be included in your source files. A difference between this and the big font is that the coordinates are the other way around in memory. Big font has _curRow and then _curCol, while menu text has _penCol and then _penRow.
_penCol		=$c37c
_penRow		=$c37d

The coordinates are set up much like the big font's except there is a greater choice because the text is smaller. The coordinates are measured in pixels. Remember that this font is called variable width font because the widths of characters differ. The coordinates are set up according to the following representation of the TI86's screen. The top left would be row 0, column 0. The bottom left would be Row 63, Column 0.

(0,0) (127,0)
(0,63) (127,63)

After you've loaded the cursor position into the above memory coordinates you load the letter, character, you want displayed into a. Then you can call the text display routine of your choice for displaying a letter or string. Note that when you use the big font, the text will wrap around to the next line if it goes over. This is not the case in menu size font. It will go over the edge of the screen. Only will a letter be displayed if the whole thing fits on the screen. Here are the routines used. I won't go into detail about the differences between strings and letters because you can read above in the big font section.

_VPutMap

Description Prints one menu text size letter at the menu text cursor position and does not advance the cursor.
Inputs A is the character to be printed.
Destroys af, de, and ix
Output A is printed on the screen in its ASCII equivolent in menu text and the cursor position is still the same. The carry flag is set if the letter wouldn't fit on the line.

_VPutS

Description Prints a string of characters until it encounters $00.
Inputs hl holds the address of the string to print.
Destroys hl holds address of byte after $00. A holds the last character displayed.
Output hl string is printed on the screen in its ASCII equivolent. The cursor coordinates are updated to the position after the last character of the string that was displayed whether they are valid (on the screen) or invalid (off the edge of the screen) coordinates. The carry flag is set if the entire string was able to be displayed, or reset if the string ran off the edge of the screen.

_VPutPS

Description Prints a string of characters whose length is determined by the leading byte.
Inputs hl holds the address of the string to print.
Destroys hl holds address of byte after $00. A holds the last character printed. B is $00.
Output hl string is printed on the screen in its ASCII equivolent. The cursor coordinates are updated to the position after the last character of the string that was displayed whether they are valid (on the screen) or invalid (off the edge of the screen) coordinates. The carry flag is set if the entire string was able to be displayed, or reset if the string ran off the edge of the screen.

Here are some examples of using the above routines.

	ld hl,stupid_string	;string to print
	ld bc,256*8+4		;column 4, row 8
	ld (_penCol),bc		;loads c into _penCol
				; and b into _penRow
	jp _vputs		;print it and return
stupid_string:	.db "2+2=4",0	;string
	ld hl,stupid_string	;string to print
	ld bc,256*50+40		;column 40, row 50
	ld (_penCol),bc		;loads c into _penCol
				; and b into _penRow
	call _vputps		;print it
	ret			;return
stupid_string:	.db 5,"2+2=4"	;string
	ld a,$20		;character to print
				;this in hexadecimal and
				; is the same as
				; "ld a,' '" or "ld a,32",
				; or "ld a,Lspace"
	ld bc,120+256*8		;column 120, row 8
	ld (_penCol),bc		;loads c into _penCol
				; and b into _penRow
	jp _vputmap		;print it and return

Font Options

There are a few different ways you can display your text on the screen. You can turn on or off these options using the System Flags of TI-OS. The basics of these system flags is that the options stored as bits in a byte. They are either on (set) or off (reset). The text printing routines store their option byte in a table with all the rest of TI-OS's flags. The table starts at $c3e5 with the text flags being 5 bytes after the start (at offset 5). The TI86 keeps iy holding the address of the start of that table.

Let's say we wanted to turn on the option that prints white text with a black background, called Reverse Video Print or Inverse Video. We execute the following command to set that bit (bit 3). The first line is the command with the aliases as defined in ti86asm.inc and the second line is with the actual numbers instead of aliases. The are both the same, either is perfectly acceptable; however, it is better to use the names for writing better code.

	set textInverse,(iy+textFlags)	;write text on
					; black background
	set 3,(iy+5)

To turn it off we do this:

	res textInverse,(iy+textFlags)	;normal black text on
					; white background
	res 3,(iy+5)

Here is a table showing the bit offsets in the Text Flag Byte.

Bit Bit Alias Name Description
1 _textEraseBelow Erase Line Below When set it erases the line below the menu character being printed.
2 _textScrolled Scroll Will be set if the screen had to be scrolled up during the last printing of big text.
3 _textInverse Inverse When set, it prints white letters on a black background; when it's reset, it prints the normal black letters on a white background.

There is, however, another flag that is in the option byte at offset 24 from iy that tells the TI86 to either print the menu text on the graph screen of on the regular display. Set it to write to the display, reset it to write to the graph screen (plot screen).

	set textWrite,(iy+new_grf_flgs)	;write on display screen
	res textWrite,(iy+new_grf_flgs)	;write on graph screen


More from z80 » Intermediate
All the Flags // Debugging // Down-Left Bug // _GetKey Codes // Logical Operators // Memory, ROM, RAM, and Safe Areas // Miscellaneous Instructions // PC and SP // Random Numbers // TI's ROM Calls // Restart Commands // Simulated 16-bit Addition // The Stack // Tables and Arrays // Text Display // Variables