Frequently Asked Questions


  
The FAQ list is now organized into several categories. Here you will see the list of (briefly expressed) commonly asked questions. Please click the question you want, to get the full form of the question and the related answer. Note, however, that some questions/answers are quite related, and some answers are logical consequence of previous ones. So, after reading the answer, it is recommended to browse through surrounding quesion/answer pairs too, to get a more complete information.

Visit also the
TIGCC Programming Message Board. A lot of interesting topics about TIGCC programming are discussed there.




The C Language
Floats
Compatibility
TI-Basic and C
Graphics and display
Assembly and C
Strings
Event-driven programming, menus, and throwing errors
TI variables and the Variable Allocation Table (VAT)
Memory, C variables, and pointers
Input: Keyboard and link
Miscellaneous



Q: Is there any examples available on the net from which it is possible to learn something more...
A: The best solution would be if I will wrote a tutorial. Unfortunately, I have not enough time to write tutorials, small examples, etc. Some examples come with TIGCC starting from release 0.6, but this is probably not enough. I know that some people work on making TIGCC tutorial, but as far as I know, all of them are in a very early state. I suggest first learning C language (not C++) on some big computer (PC, Mac, etc.). A very good list of generic C language tutorials may be found on TI-Chess Team Home Page. After learning the basics of C, reading the documentation of TIGCCLIB will be enough to learn how to apply this to the TI programming. In addition, try to look my programs like creversi, cblaster and scott (scott is in advint.zip archive), all of them are in TI-89 assembly games directory on ticalc.org. Note that every day a number of TI programs written in C increases, so there is now a lot of open-source C programs which can be found on ticalc.org.

Q: I need floats in my program, usage of floating point values is very awkward...
A: Well, well... After a lot of hard work, TIGCC now (starting from release 0.9) supports standard handling of floating point values. Happy?

Q: My program compiles fine with previous releases of the library, but now I get a warning message
warning: 'return' with a value, in function return void
somewhere in the body of the '_main' function. What happens?
A: Nobody asked this question yet, but I expect that it will be a common question in the future. See, you can not return an exit code from '_main' to the TIOS, that's why '_main' should be a void function (in opposite to the 'main' function on "real" computers, which should be an int function). This release of the library explicitely warns the user if he/she tried to use 'return' statement with a return value inside '_main' function (if enough strong level of warning checking is enabled). This warning is not anything dangerous: it is here just to inform user that the returned value will be ignored. To avoid this warning, simply remove the suspicious statement.

Q: I have problems with programs which return values to the TI-Basic using RETURN_VALUE directive!
A: Yes, this is a problem with AMS 2.xx. For some strange reasons AMS 2.xx does not allow ASM programs to be part of expressions any more, i.e. if 'xyz' is an ASM program, 'xyz(3,2)+5' or 'xyz(3,2)->a' is not legal in AMS 2.xx. Fortunately, there is a solution. Read what I wrote about this problem in the section How to return values to the TI-Basic.

Q: I learn C++ in a school so it will be good if I can program my TI-89 in C++ (not in ordinary C). Do you plan to implement C++ on TI-89?
A: No. Although C++ is more powerful language than C, it is not a language which is good for TI calculators. It is not efficient enough to be good for a calculator. The code generated by C++ is less efficient than code generated by ordinary C, and it is too bloated. So, even if somebody made C++ compiler for TI, I don't recommend using any C++ extensions (like classes, and especially streaming), except if you like programs like
cout << "Hello world";
which produces 5 Kb long code...

Q: I have strange problems when using floats. The most strange problem is that when I try to make a program which uses floats, the compiler displays a lot of garbage like
handle exceptions: Exception: STATUS_ACCESS_VIOLATION
handle_exceptions: Dumping stack trace to CPP.EXE.core
What is this?
A: There was a bug in GCC preprocessor which sometimes causes problems with FLT macro. As TIGCC now supports native floats, usage of FLT is deprecated, so such problems are very unlikely any more.

Q: The compiler sometimes report strange error messages on places where I really can not see any errors. For example, the compiler reports the error
parse error before 'void'
but the statement on which the error is reported was
int cexp;
I am really confused. First, I don't see any errors here, and second, I can't see any 'void' keywords here!
A: Yes, such problems may really be the source of big frustrations. There is nothing wrong with above statement, but note that 'cexp' is a function defined in timath.h header file, and you can not use this name as a name of a variable. Now you can say why you got such strange error message? See, the most of functions in TIGCCLIB are translated by the preprocessor into constructions which perform indirect function calls through a TIOS jump table. In other words, 'cexp' will be replaced by the preprocessor into the indirect function call constructor whenever it is used. So, the innocent statement like
int cexp;
will be converted into
int (*(void(**)(float,float,float*,float*))(*(long*)0xC8+1316));
which is a syntax error. And the error is just before 'void'.

I can not do anything against such hidden errors. Whenever you encounter strange errors without obvious reasons, check whether you used reserved library name for your identifier. The chance of making such errors is much smaller if you include only necessary header files than if you include general header files like tigcclib.h or all.h.

Q: Grayscale mode flickers too much on hardware release 2 calculators...
A: I thought that this was corrected starting from TIGCCLIB 1.5. OK, the flickering was reduced, but it still was unacceptable. Now, in release 2.2, I think that I done everything it can be done to reduce flickering. I have not a real HW2 calc to make experiments, but now grayscale support is tested on real HW2, and it is stable. See also GrayAdjust function which allows very fine adjusting of grayscale quality.

Q: Do you plan to implement 7-level grayscale mode?
A: So far no, because nobody yet implemented 7-level grayscale which works stable on both HW1 and HW2 calculators. I don't want to implement features which works only on HW1 calculators.

Q: Some of your examples (like the example given in the documentation for rsa.h header file) don't compile!
A: No. They compile fine, if they are typed in absolutely correctly. But there is a hardly-visible problem with the space character. The space between the macro name and the argument list is strictly forbiden, else the macro will be treated as an argumentless macro. In other words, you must not type
#define GetBignumArg (ap, bn) \
instead of
#define GetBignumArg(ap, bn) \
Hardly visible, isn't it?

Q: When I tried to compile my program, the linker reports to me
Undefined reference to ...
although my program seems correct. What's a problem?
A: In earlier releases of TIGCC (before 0.9) this usually means that you need to include some patches in your program. As TIGCC now does it automatically, if you still have an undefined reference error, that either something is wrong with your program (more probably you used a function which is not defined elsewhere, maybe due to typing error), or you used something which is not implemented yet in TIGCC (which is probably true if you got an undefined reference to a symbol which begins which the double underscore '__'). For example, although TIGCC supports very long (64-bit) integers ('long long' type, which is a GNU C extension), the support for multiplying and dividing double longs is not supported yet. For example, if you try to divide two double-long numbers, you will get an undefined reference to '__udivdi3'. Sorry, there is no simple help for this. You must live without 64-bit division for now. It will be implemented in the future.

Q: I wonder why you put '-O2' as a default optimization option in the compiler. '-O3' will perform better optimization...
A: Yes, but '-O3' produces bigger output than '-O2', because it performs loop unrolling and inlining of "short-enough" functions...

Q: Is there any method to use a DoorsOS library with TIGCC (such as ZipLib) and how to call a routine that uses something other than the stack in the routine for arguments passing?
A: Good and common question. When an assembly routine uses register passing, the solution is not so obvious. I will give a concrete example. Look at ZipLib, function compress. This is a cite from DoorsOS documentation:
; compress ()
; Function: compress data
; Input: A0   = Pointer to uncompressed data
;        A1   = Pointer to where the compressed data
;               should be stored
;        D0.W = Length of datas which will be compressed
; ziplib::compress equ ziplib@0004
So, how to interface this with TIGCC? There is a lot of solutions. One solution is to use an interface function which accepts parameters via stack then to use embeded assembler to call library function:
void compress (void *src, void *dest, unsigned short len)
{
  asm ("move.l (%a6,8),%a0
        move.l (%a6,12),%a1
        move.w (%a6,16),%d0
        jsr ziplib__0004");
}
This works, but maybe it is awkward to know where the parameters are stored on the stack. GNU C has some extensions for interfacing with assembler, so the following solution is more elegant:
void compress (void *src, void *dest, unsigned short len)
{
  asm ("move.l %0,%%a0" :: "g"(src));
  asm ("move.l %0,%%a1" :: "g"(dest));
  asm ("move.w %0,%%d0" :: "g"(len));
  asm ("jsr ziplib__0004");
}
If you don't understand this (which is probably the case if you are not familiar with GNU C extensions), accept this as as-is template.

Both solutions have two bad points: first, usage of stack is awkward if you want very fast calling. Second, this interface function will always be inserted in the code (even if not called in the program), so it is not suitable for making universal header files. As GNU C allows interfacing arbitrary C expressions with assembler, and allows building smart safe macros using so-called "statement expressions", the following solution avoids both the stack and "embedding" problem:
#define compress(src, dest, len) \
  ({ asm ("move.l %0,%%a0" :: "g"(src)); \
     asm ("move.l %0,%%a1" :: "g"(dest)); \
     asm ("move.w %0,%%d0" :: "g"(len)); \
     asm ("jsr ziplib__0004"); })
In any case, you can call function (or macro) "compress" using, for example,
compress (LCD_MEM, buffer, LCD_SIZE);
etc.

The third solution has one drawback: the impossibility of compile-time checking of parameters type. This can be solved using the following construction (don't be afraid by introducing extra variables; the compiler will remove them during the optimization, and it will produce the same code as in previous example, but with type-checking):
#define compress(src, dest, len) \
  ({ void *__src = (src), *__dest = (dest); \
     unsigned long __len = (len); \
     asm ("move.l %0,%%a0" :: "g"(__src)); \
     asm ("move.l %0,%%a1" :: "g"(__dest)); \
     asm ("move.w %0,%%d0" :: "g"(__len)); \
     asm ("jsr ziplib__0004"); })
There is also fifth, nearly "ideal" solution, using GNU cast constructors which constructs a function during the compilation (look how functions in stdio.h are implemented, etc.). But, I will not present this here, because you will not understand anything if you are not familiar with cast constructors.

Q: Do you know how I can use sprites with TIGCC?
A: Another common question. The answer depends of the size of the sprite. You can use put_sprite rutine from DoorsOS graphlib, by making an interface using methods described in previous answer. But if your sprite is not wider than 32 pixels (which is likely), then you can now use sprites.h header file. This header file defines fast functions which work with sprites (including masked sprites). The only limitation is that the sprite must not be wider than 32 pixels (the height is not limited). Note that routines in the FAQ list presented with TIGCCLIB 1.5 have some bugs (PutSpriteAnd does not work correctly). This is now corrected. Also, some syntax errors were presented in the sprite definition. Function Sprite16 from sprites.h was buggy in release 2.0 of TIGCCLIB; this bug is also corrected now.

What to do if you want sprites wider than 32 pixels, and don't want to use DoorsOS? The answer depends of what will be usage of this sprite. If you don't need fast action, built-in function BitmapPut may be good enough. If you need a very fast sprite routine, then, huh... you must write it by yourself...

Q: I can't understand how sprites are defined; I looked in many program sources, and every sprite definition looks for me as an array of random hex numbers!?
A: YACQ. Well, suppose that you want to make a sprite which is a filled circle. Make a grid on the paper, and make a sprite shape by filling grid squares. Then, replace each filled square with 1 and each blank square with 0. In above example, it may looks like:

000111000
001111100
011111110
011111110
001111100
000111000

Then, look produced rows as a set of binary numbers, and convert them to hex. For example:

000111000 binary = 38 hex
001111100 binary = 7B hex

etc. These hex numbers describes the sprite, i.e. the sprite definition should be
unsigned short sprite [] = {0x38, 0x7B, ...};
assuming that Sprite16 will be used. That's all...

Q: Excuse me, but what does the word "YACQ" in the previous question mean?
A: "Yet Another Common Question" :-)

Q: I would like to know if it is possible to use the sprite functions in sprites.h with grayscale. I have tried using the Sprite16 function with grayscale, and none of the sprites I intended to be in grayscale appeared. I tried to use DrawIcon and the grayscale worked just fine. But DrawIcon is too slow... Can Sprite16 and Sprite32 handle grayscale sprites.
A: Very common question in a recent time. See, you probably tried to use SetPlane. Sprite16 have a parameter for drawing plane, so it is not sensitive to SetPlane: you need to give the plane as an explicite parameter. In fact, you need to have two different sprite planes and to draw a sprite twice, passing two different planes as a parameter. For example,
static unsigned short light_definition [] = {...};
static unsigned short dark_definition [] = {...};
...
Sprite16 (x, y, height, light_definition, GetPlane (LIGHT_PLANE), A_XOR);
Sprite16 (x, y, height, dark_definition, GetPlane (DARK_PLANE), A_XOR);
In other words, sprite routines can handle grayscale sprites, but not natively. Meaning you have to take your grayscale sprite, split it into two layers, and draw each one separately on its own plane - the routine does not handle these by itself. As suggested by Scott Noveck, it is possible to make a function of your own to handle this. Assume that your grayscale sprites follow the "standard" format seen in the most of ASM games, with the dark plane data followed immediately by the light plane data. This routine will call Sprite16 twice - once for each plane:
void GraySprite16 (short x, short y, short h, unsigned short *spr, short mode)
{
  Sprite16 (x, y, h, *spr, GetPlane (LIGHT_PLANE), mode);
  Sprite16 (x, y, h, *spr + h, GetPlane (DARK_PLANE), mode);
}
Don't be afraid about calling GetPlane each time: it is not a waste of time. Its implementation is smart: when the input is a constant, it will simply evaluate to a memory address that contains the pointer; when it is variable, it expands to a simple macro.

Q: How can I convert an integer or a float to a string?
A: YACQ, with a straightforward answer. It's easy. Use sprintf. For example:
char string1[50];
char string2[50];
short int var1;
float var2;
...
sprintf (string1, "%d", var1);
sprintf (string2, "%f", var2);
That's why there is no need for functions like itoa and ftoa in opposite to atoi and atof.

Q: I am just curious how I can write my own and efficient IntToStr routine...
A: Process the number starting from the end (i.e. from the least significant digit instead from the most significant digit), like in the following example, which is probably the most optimal code:
char *IntToStr (unsigned long an_integer)
{
  static char result [] = "          \0";    // 10 spaces and \0
  char *ptr = result + 10;
  while (an_integer)
    {
      *ptr-- = an_integer % 10 + '0';
      an_integer/=10;
    }
  return ptr;
}
Note that 'static' before char in the first line is essential: without it, the variable 'result' will be allocated of the stack, so it will not live too long after this function returns. Returning any pointers which points to structures allocated on the stack is extremely dangerous (it is not only dangerous; it is almost completely nonsense, except if you performs some really nasty and bizzare hacks). The another solution (but less elegant) is to make 'result' global (i.e. to define it out of the function).

Q: How I can define a comparison function for sorting an array of floats using qsort function:
A: The best solution is
long flt_comp (void *a, void *b)
{
  return fcmp (*(float*)a, *(float*)b);
}
Here is a simple example of usage:
float list[5] = {2.5, 3.18, 1.42, 4.0, 3.25};
int i;
...
qsort (list, 5, sizeof (float), flt_comp);
for(i = 0; i < 5; i++) printf("%f\n", list[i]);
Simple, isn't it?

Q: Is it hard to display a PIC variable created from TI-Basic in C programs?
A: No, it is easy. It is enough to locate the variable (using SymFind for example), and to display its content using BitmapPut (its content is just as expected by BitmapPut function). To be more concrete, look the following function:
short show_picvar (char *SymName, short x, short y, short Attr)
{
  SYM_ENTRY *sym_entry = SymFindPtr (SymName, 0);
  if (!sym_entry) return FALSE;
  if (peek (HToESI (sym_entry->handle)) != PIC_TAG) return FALSE;
  BitmapPut (x, y, HeapDeref (sym_entry->handle) + 2, ScrRect, Attr);
  return TRUE;
}
Usage of this function is straightforward, for example:
show_picvar ($(testpic), 30, 30, A_NORMAL);
assuming that "testpic" is the name of wanted PIC variable. This function returns TRUE if the operation was successful, else returns FALSE (i.e. the picvar does not exist, or it is not a PIC variable).

Q: Can you give me info on how BitmapGet works. I've tried everything that I know and I still get protected memory errors. The manual just doesn`t give anything solid to base a few lines of code on.
A: You probably didn't allocate enough space to store a bitmap. The simplest way to do so is given in this example:
#include <tigcclib.h>

int _ti89;

void _main (void)
{
  SCR_RECT full_screen = {{0, 0, 159, 99}};
  char buffer [BITMAP_HDR_SIZE + 160*100/8]; // or 2004 if you like it more
  BitmapGet (&full_screen, buffer);          // store screen in buffer
  clrscr ();
  printf ("Press any key to\nrestore screen...");
  ngetchx ();
  BitmapPut (0, 0, buffer, &full_screen, A_REPLACE);
  ngetchx ();
}
Note that this is just an example: for saving/restoring the whole screen, functions LCD_save and LCD_restore are much more efficient! And, 'buffer' will probably be allocated using malloc in a more realictic example...

Q: If my program stops execution by throwing an error, I cannot execute it again without retransmitting it from the computer or another calculator. Namely, when I try to execute it again, the calculator reports "Invalid program reference". Why, and what I can do to prevent such behaviour?
A: See, the program handle is locked during the execution. Now, if the program terminates abnormally (i.e. by throwing an error), its handle will remain locked forever. This in fact prevent running it again. The best method to prevent such behaviour is to execute the complete program under the error handler, which will guarantee that the program will always terminate proprely. The best method to achieve this is to do:
void _main (void)
{
  TRY
    main_prog ()
  ONERR
    ERD_process (errCode)  // or more sophisticated error hanling
  ENDTRY
}

void main_prog (void)
{
  // Put your program code here
}
There is no need to do so in "Doors" mode, because DoorsOS do this automatically.

Q: When I try to turn the calculator off using off function from system.h, nothing happens. What is wrong?
A: Most probably, you wrote
off;
instead of
off ();
This is very common misinterpretation of usage of argument-less function. You may ask why the compiler did not display any errors? See, whenever you use the function name alone (without the parenthesis), it is automatically converted to a pointer to the function (this is very useful feature if used properly). So, 'off' alone is interpreted as a pointer, so you have an statement which consists of an effect-less expression, similarly as if you wrote
2 + 3;
This is not illegal in C, but it has no any effect (eventually, you will be warned by the compiler that the statement has no effect, if you enable enough strong warning checking). Such misinterpretations are very often with newbie users, so I will elaborate this in more details. Suppose that you wrote
key = ngetchx;
You probably want to call ngetchx function to get a keypress, but instead, you will assign the address of this function to the variable 'key', because the function name without parenthesis is automatically converted to a pointer (however, you will be warned by the compiler that it is very ugly to assign a pointer to an integer variable without an explicite typecast). Instead, you need to write
key = ngetchx ();
Sometimes, you will not get even a warning. Look the following example:
void *qptr = kbd_queue;
The intention was probably to put the address of the keyboard queue into the 'qptr' variable, but instead, the address of the function kbd_queue itself will be taken! As the function name is converted to a pointer to a function, and as you assign it to a void pointer (which is assign-compatible with all other pointer types), you will not get even a warning!

Q: I have problems with allocating memory with TIGCC. When I run my program the first time, it works just as expected, but the second (or sometimes the third) time I run it, it hangs. Typical memory allocation problem. But I just can't understand what the problem is.
A: The problem is very probably not related to the dynamic memory allocation, but to the usage of static variables. At the moment, all static vars need to be initialized, even to nothing. I.e, you need to use
static int a = 0, b = 0;
static char *ptr = NULL;
instead of
static int a, b;
static char *ptr;
I expect that this will solve your problems. I hope that Xavier will implement automatic initialization of all static data in the near future.

Q: I can't understand matrices in C (not TI-Basic matrices, but matrices which are the part of the C language)!
A: Basically, to declare a matrix, you need to use:
type name[dimension1][dimension2];
for example:
int a[5][5];
And, to access element of the matrix, you need to use:
name[index1][index2];
for example:
a[2][3] = 10;
or
x = a[1][2];
But note that indices are not from 1 to dimension, but from 0 to dimension-1. So, in the above example, both indices are in range 0 to 4, not 1 to 5. For example to fill all matrix by zeroes, you can use this code:
int a[5][5], i, j;     // A 5x5 array of ints, and two single ints
for(i = 0; i < 5; i++) for (j = 0; j < 5; j++) a[i][j] = 0;
although the experienced C programmer will simply use
memset (a, 0, 5 * 5 * sizeof(int));
to make it faster.

Q: I have problems with linking a multimodule program (i.e. the program which is spreaded in several modules which are compiled independently in separate object files). It seems that there is a problem with external variables...
A: Note that the behaviour of TIGCC linker is still quite suspicious when linking multiple object files. So, for a while, try to avoid them. The easiest method for doing so is to include statements like this
#include "module1.c"
#include "module2.c"
...
in the main module. Yes, it is not nice (it makes compiling time much longer for complex projects), but it works...

Q: How do you store preferences, high scores, and suchlike so that they do not go away when you exit the program? I have absolutely no clue how to do this.
A: The simplest method is: if you stored preferences in an array, declare this array as "static". For example,
static int high_scores[10] = {};
In this case, such array will be kept in the program file itself (instead on the stack), so it will not go away after you exit the program. This method has only one drawback: preferences will not be kept if the program is archived.

Be aware of the initializer: static variables must be initialized in the "nostub" mode. An empty initializer in this example is equivalent to the
static int high_scores[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Don't be confused which such initialization. It seems that the array elements will be set back to 0 any time when you run the program. But, this is not true. The initialization of automatic and static variables is quite different. Automatic (local) variables are initialized during the run-time, so the initialization will be executed whenever it is encountered in the program. Static (and global) variables are initialized during the compile-time, so the initial values will simply be embeded in the executable file itself. If you change them, they will retain changed in the file.

Q: If I understand correctly, if I have the following global variable in my program
int a = 10;
and if I change its value somewhere in the program to 20 (for example), its initial value will be 20 (not 10) when I run the program next time???
A: Exactly! Note that this is true only for global and static variables (see also the previous question). To force reinitializing, you must put explicitely something like
a = 10;
at the begining of the main program!

Note, however, that if the program is archived, the initial values will be restored each time you run the program, because archived programs are reloaded from the archive memory to the RAM on each start, similarly like the programs are reloaded from disks on "standard" computers (PC, etc.) each time when you start them.

Q: How can you control where a program data is stored in the calculator's memory, and then how to access the data? By looking at your programs (cblaster etc.), you simply use memcpy to write to the array, which seems so easy! Is the array kept in memory because it's declared as static?
A: Yes. Every static and global data (i.e. data which are declared out of functions) are kept in the .89z/.9xz file itself (more precise, in the area of the memory allocated to .89z/.9xz file), so they will survive after the end of the program. Local data are stored on the stack (so they will be deleted after the end of the function in which they are declared).

Q: You quote very often in the documentation that we need to avoid global variables as much as possible. What is so wrong with them?
A: Of course, globals are sometimes very necessary, but they are also easy to overuse. The good programming practice is to keep the scope of each identifier as small as possible. But, in addition to conventional programming theory, there are some extra reasons against globals which are related particularly to programming on TI calculators. First, every global variable is translated to the absolute addressing mode. As this mode is non-relocatable, the compiler adds a 4-byte long entry into the relocation table for each apperance of the global variable. If global variable "a" is mentioned say 100 times in the program, this is extra 400 bytes. When I ported some programs from PC to TI, I suceeded to reduce program space from 20K to 16K just by eliminating globals. And 4K of space is quite worth on TI... Second, globals are kept in the .89z (or .9xz) file itself. Sometimes it is good (to keep permanent data which will survive after the program exits etc.), but very often it is a wasting of file space (as the file length is limited). Read questions given further in this document to see how to reduce a file size if you have a strong reasons for using global arrays. To learn: avoid extensive usage of globals as much as possible!

Q: According to what I have read, you cannot store an immediate value (or any non-pointer variable) to a pointer variable. You can only copy pointers of the same type and such. Now, the books may say this, but, is there a way to do this somehow? I want something like 'address=0x001fca;' where address is a pointer to a char. Is it necessary to use the assembler for this?
A: No. C is enough low-level language that nearly everything which can be done in ASM can be done in pure C too (of course, pure ASM code is usually faster). In your concrete example, using of typecasting is quite enough:
address = (char*)0x001fca;
This is really a classic usage of the typecast operator. It is extremely powerful in C language, so it may be used to convert nearly everything to anything. This sometimes may be really terrible. For example, in TIGCCLIB implementation, I used very strange typecasting to convert an array to a function. And, nearly all TIGCCLIB functions are implemented using a typecast operator which constructs an indirect function call. For example, when you use something innocent like
DrawStr (0, 0, "Hello", A_NORMAL);
the preprocessor expands it into a really terrible typecast:
(*(void(**)(int,int,char*,int))(*(long*)0xC8+0x6A4))(0,0,"Hello",A_NORMAL);
Nasty?

Q: Is it possible to add two bytes or even one byte to a longword pointer? I am using a longword pointer to write longwords to the screen, and I need to add 30 bytes to it to get to the next line. However, I can only add multiples of four bytes to it...
A: It is possible using typecasting:
ptr = (long*)((char*)ptr + 30);
Don't be afraid, the compiler will generate just addition: everything other is just to satisfie type checking conventions. Or alternatively, you can use even simpler form:
(char*)ptr += 30;
Although such form is not requested to work in ANSI C standard, the most of compilers (including TIGCC) will accept this.

Q: Why doesn't this work?
void *screen_ptr = LCD_MEM;
*screen_ptr = 0xFF;
When I do this, I get the error "Invalid use of void expression" at the second line. Can't you assign a value to a dereferenced void pointer? If not, what good is a void pointer?
A: You can not dereference a void pointer, without an explicite typecasting, because the compiler can't know the size of an object pointed to by it. You can do an explicite typecast:
*(char*)screen = 0xFF;
Or better, if you need to dereference it often, then declare
unsigned char *screen = LCD_MEM;
i.e. avoid void pointers for this purpose (continue reading to see why such assignment is legal, i.e. assigning LCD_MEM which is a void pointer to a char pointer).

Void pointers are used mainly as arguments of functions which represents memory addresses, no matter what is the object located at that addresses. Then, any pointer type (including arrays, which are in fact pointers to the first element of the array) may be passed to such function without warnings and without needness for explicite typecasting. For example, memcpy is such function, and it is declared as:
void *memcpy (void *source, void *destination, unsigned long len);
Ignore returned type for a moment. So, you can do
memcpy (LCD_MEM, buffer, 3840);
but you also can do
memcpy (a, b, 10 * sizeof(long));
assuming that you have declared
long a[10], b[10];
somewhere in the program. Second, void pointers may be assigned to any other pointer type and vice versa without and warnings and without needness for explicite typecasting. They are usually returned as the result of functions which don't make any assumptions what will be purpose of returned pointer. For example, malloc is such function. It is declared as
void *malloc (unsigned long len);
So, assuming that you have declared
char *a;
int *b;
long *c;
you can do
a = malloc (100);
b = malloc (30 * sizeof(int));
c = malloc (50 * sizeof(long));
without any problems.

Q: I have a variable and a pointer to it, for example,
int a, ptr_to_a = &a;
When I tried to modify the variable "a" indirectly using the pointer, like in
*ptr_to_a++;
the compiler reports to me "Value computed is not used". What is wrong here?
A: Note that although operators '++' and '*' have the same precedence, '++' will be evaluated first, so this expression will be evaluated as
*(ptr_to_a++);
i.e. it increases the pointer, then reads the value from it (which is not used for anything). This is not what do you want, of course. To perform what do you want (i.e. to increase the variable pointed to by the pointer), use parentheses to change the order of evaluation, i.e. use
(*ptr_to_a)++;
This will work as expected.

Q: Whenever I used strcat in my program, it crashes!?
A: See, you probably want to ask what is wrong in the following code:
printf (strcat ("Hello ", "World!"));
strcat appends the second argument to the first argument and returns the augmented first argument, but it does not allocate any extra space for doing this task. So, if you do
strcat ("Hello ", "World!");
string "World!" will be copied over bytes which follows immidiately after bytes "Hello " in the memory (whatever is there), which will nearly surely cause a crash (because there is probably a part of code or other data there). So, strcat may be used only when the first argument is enough long buffer, like in:
char buffer[50];
strcpy (buffer, "Hello ");
strcat (buffer, "World!");
In other words, C language does not support dynamic string manipulations which is present in some other languages like Basic, Turbo Pascal, etc.

Q: I would like to have a global screen buffers which need to be allocated dynamically (to avoid wasting space in the program). The problem is that global variables must be initialized. In your programs, you define the buffer in the _main function, but then they are not available in the other functions. Is there a way to make "global" non-initialized screen buffers?
A: Declare a pointer initialized to NULL, then at the beginning allocate the buffer with malloc. For example, do this:
#include <tigcclib.h>
...
void *buff = NULL;  // Buffer pointer, initialized to NULL
...
void _main(void)
{
  ...
  buff = malloc (LCD_SIZE); // Alloc buffer, make "buff" points to it
  if (!buff) ...            // Do some error handling (no memory)
  LCD_save (buff);
  ...
  LCD_restore (buff);
}
Simple?

Q: My program works in "Doors" mode, but it doesn't compile in "nostub" mode?
A: Very probably, you got the error message:
Error: Fatal: _nostub is not compatible with BSS blocks
This means that you have uninitialized global variables. In "nostub" mode all global variables (i.e. variables which are defined out of any functions) MUST be initialized. Uninitialized globals are stored on BSS section which is not support in TIOS itself, only in DoorsOS. That's why uninitialized globals doesn't work in "nostub" mode. See, if X is a global, instead of
int X;
you need to write
int X = 0;
even if you don't need to have an intitial value. If you want to have global array, instead of
int A[10];
you need to write
int A[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
or simply (this is the same):
int A[10] = {};
But, having a large global (initialized) array have a big drawback: increasing size of .89z or .9xz file, because INITIALIZED global arrays are stored in the file itself. So if you have global declaration
int A[5000] = {};
you will increase size of your file by 10K (5000*sizeof(int)). What to do? Use locals as much as possible. But, if you need to have big global arrays, use dynamic allocation. Instead of
int A[5000] = {};
use
int *A = NULL;
Then, you need to do (at the begining of your main program):
A = calloc (5000, sizeof (int));
to allocate 5000 elements to array A. See also the previous question.

Q: Your hints about dynamic creation of arrays work fine for one-dimensional arrays. But I need a global matrix. There is no problem if the matrix is small. But, if I simply put
int A[200][100] = {{}};
I will increase the size of my program by about 40K (200*100*sizeof(int)). This is really unacceptable. Obviously, I need to create a matrix dinamically. But I have no any idea how to do this.
A: Very good question. Solving this problem requires good knowledge about how arrays and pointers are related. As this question usually has unadequate answers in various C books, I will elaborate this topic (dynamic matrix) in more details.

One method, which is often recommended in books, is usage of array of pointers. Using this method, you need to allocate each row of the matrix separately. For example,
int *A[200] = {};   // An array of pointers
...
for (i = 0; i < 200; i++)
  A[i] = calloc (100, sizeof (int));
assuming that all memory allocations were sucessfull. Note that the initializer '{}' is not necessary if 'A' is not global (but we will assume that it is). Of course, you need to free allocated memory too at the end of the program. We will see a bit later why this method is not recommended on TI calculators.

Using this method, you will have a global array which is 800 bytes long (200*4, where 4 is the size of a pointer), which is much smaller than 40000 bytes. And, you need to know a number of rows in advance. Some books suggests a method which does not use any extra space in the executable file, and in which you need not to know any dimensions of the matrix in advance. This method uses a double pointer (pointer to pointer):
int **A = NULL;
...
A = calloc (200, sizeof (*A));
for (i = 0; i < 200; i++)
  A[i] = calloc (100, sizeof (int));
The major drawback of both methods is complicated memory management. In a real program, you need to be aware of a fact that each allocation may fail eventually, and you need to act accordingly if this happens. And, these methods are too expensive for TI calculators. As TIOS memory manager assigns a handle with each allocated block, reserving say 200 handles for just one matrix is too expensive, if even possible, because the total number of free handles is limited!

What to do? The best solution is so simple, but rarely documented in books. Instead of using an array of pointers, use a pointer to an array! Seems strange, but only what you need to do is:
int (*A)[100] = NULL;   // A pointer to an array
...
A = calloc (200, sizeof (*A));
So, everything is done with just one calloc! And, you can free the memory just with one call to free. Wonderful, isn't it? Of course, whatever method you used, you can access to the elements of a matrix using an usual syntax like 'A[i][j]'. Note however that the last ("ideal") method requires that you know the number of columns in advance. Try to understand how all three methods work: it will help you understanding nontrivial pointers, arrays and relations between them.

As many users ask me about creating dynamic matrix, I will give here a complete demo program for newbies which creates and prints elements of dynamically created matrix, using the third (the best in my opinion) method:
#define SAVE_SCREEN

#include <tigcclib.h>

int _ti89, _ti92plus;

#define M 10
#define N 5

int (*A)[N] = NULL;

void _main (void)
{
  int i,j;
  A = calloc (M, sizeof (*A));     // allocation
  for (i = 0; i < M; i++)
    for (j = 0; j < N; j++)
      A[i][j] = i*j;               // fill 'A' with the multiplication table
  clrscr ();
  for(i = 0; i < M; i++)
    {
      for (j = 0; j < N; j++)
        printf ("%2d ", A[i][j]);  // print out the matrix
      printf("\n");
    }
  free (A);                        // free the memory
  ngetchx();
}
This method is really ideal if you know dimensions of the matrix in advance (which is usually true). It may be easily extended to create dinamically arrays with more than two dimensions. For example, to create dinamically array which behaves like
int A[M][N][P][Q];
where 'N', 'P' and 'Q' are known in compile-time, you can do:
int (*A)[N][P][Q];
...
A = calloc (M, sizeof (*A));
However, if you don't know any dimension of the matrix in advance, the second method is preferable (but see also the next question).

Q: I need variable-size arrays, i.e. arrays which size is not known in compile time...
A: In general, making variable-size arrays in C is extremely easy for one-dimensional arrays. Instead of
int a[n];  // where n is not known in compile-time
you can write:
int *a;
...
a = calloc (n, sizeof (int));
The same is not-so-easy for 2-dimensional arrays (see the previous question), and quite hard (although possible) for n-dimensional arrays where n>2. To do this, you need to have nasty plays with pointers. It is even possible to make a function named multi_dim which creates multidimensional variable-sized arrays. I once created such routine for some internal purposes (note that it is very tricky). Principally, its usage is like this: if you want to simulate
int a[n1][n2][n3][n4];
where n1, n2, n3 and n4 are not known apriori, you need to do:
int ****a;  // yes, quadruple pointer!!!
...
a = multi_dim (4, sizeof (int), n1, n2, n3, n4);
However, TIGCC is GNU C, and it has some extensions in addition to "standard" C. For example, it allows variable-size arrays without any tricky plays with pointers!!! Try this:
void _main(void)
{
  int m, n, p;
  m = random (5);
  n = random (5);
  p = random (5);
  {
    int a[m][n][p];
    // do something with a
  }
}
and you will see that it works! Look at braces before array declaration. They are necessary, else you can not insert a declaration after executive statements (i.e. after an assignment).

Q: How I can change the port for the screen memory to draw to it, and then copy it back to the regular address?
A: Do this:
void *virtual = malloc (LCD_SIZE);  // Allocate the buffer
...
if (!virtual) ... // do some error handling - not enough memory!
PortSet (virtual, 239, 127); // redirect drawing routines to buffer
or, even simpler, virtual screen may be simply in any local variable which is enough long:
char virtual[3840];
...
PortSet (virtual, 239, 127);
Note that, in this case, virtual memory will be in fact somewhere on the stack. There is nothing bad in this, but keep in mind that the total amount of the stack is 16K, so don't put TOO MANY data (like big arrays etc.) on the stack (i.e. in local variables). If you really need to handle a lot of data, use malloc instead.

After this, do any drawing you want - it will be redirected to the virtual screen. To copy this to the regular screen (i.e. to display it) do this:
memcpy (LCD_MEM, virtual, LCD_SIZE);
or even simpler (this is the same):
LCD_restore (buffer);
And, don't forget to do PortRestore before end of the program, else TIOS will be fooled after returning to TI-Basic!

Q: How I can setup properly a SCR_RECT structure? For example, the FillTriangle function requires the parameter of SCR_RECT type. How to put coordinates into it, so that I can change the clipping area for the screen?
A: If all coordinates of clip area are known in advance (for example 5, 5, 90, 70), do this:
FillTriangle (10, 10, 10, 50, 50, 50, &(SCR_RECT){{5, 5, 90, 70}}, A_NORMAL);
or, using "standard" C (i.e. without GNU extensions):

SCR_RECT area = {{5, 5, 90, 70}};  // somewhere in the declaration part
...
FillTriangle (10, 10, 10, 50, 50, 50, &area, A_NORMAL);
Note that double braces are necessary because SCR_RECT is an union.

If coordinates are not known in advance, for examples if they are in integer variables a, b, c and d, you can do this:
SCR_RECT area;
...
area.xy.x0 = a;
area.xy.y0 = b;
area.xy.x1 = c;
area.xy.y1 = d;
FillTriangle (10, 10, 10, 50, 50, 50, &area, A_NORMAL);
or, much simpler, using GNU C extensions (now, "area" is a local-scope variable initialized with non-constant initializer, which is legal in GNU C):
{
  SCR_RECT area = {{a, b, c, d}};
  FillTriangle (10, 10, 10, 50, 50, 50, &area, A_NORMAL);
}
Note that with non-constant coords you CAN NOT use something like
FillTriangle (10, 10, 10, 50, 50, 50, &(SCR_RECT){{a, b, c, d}}, A_NORMAL);
because non-constant cast constructor is not an lvalue, so "&" operator is illegal. If you don't understand this, don't worry. Simply remember that you can not do this.

Q: Well, I need to know more about lvalues and GNU C initializers and cast constructors. Especially, I need to know why I sometimes get an error message "invalid lvalue in unary '&'"...
A: Click here to see everything about GNU C extensions. But if you are lazy to read too much, I will be more concrete here. First, in GNU C (TIGCC is GNU C), initializers may be non-constants. For example,
int a = 3, b = 4, c = 5, d = 6;
int array[4] = {a, b, c, d};
is quite legal. That's why
int a = 3, b = 4, c = 5, d = 6;
SCR_RECT myScr = {{b + a, b - a, d + c, d - c}};
is quite legal too. Second, GNU C has one very nice extension in addition to ordinary C: cast constructors. This is a method for constructing structures, arrays, unions etc. "on fly" by using a typecasting of an initializer to an appropriate data type, for example
(SCR_RECT){{10, 10, 50, 50}}
So, you can use
SCR_RECT myScr;
...
myScr = (SCR_RECT){{10, 10, 50, 50}};
which is impossible in ordinary C (ANSI C). You can even use
myScr = (SCR_RECT){{a, b, c, d}};
where a,b,c,d are expressions. Well, but what is now the problem? See, C has two type of objects: lvalues and non-lvalues. lvalues are objects which may appear on the left size of an assignment. For example, a variable is an lvalue and a constant is not an lvalue, because 'x=5' is legal and '5=x' (or '5=3') is not legal. Not only variables are lvalues; for example, dereferenced pointers are also lvalues, so this is legal for example (store 100 at address 0x4c00):
*(char*)0x4c00 = 100;
So, '*(char*)0x4c00' is an lvalue. Now, about the problem. In GNU C, cast constructors are lvalues only if the initializer is completely constant. I.e. '(SCR_RECT){{10,10,50,50}}' is an lvalue, but '(SCR_RECT){{a,b,c,d}}' is not. As C language accepts unary '&' operator (i.e. "address of") only on lvalue objects, this means that, for example,
&(SCR_RECT){{10, 10, 50, 50}}
is legal, but
&(SCR_RECT){{a, b, c, d}}
is not! This is the real cause of the problem!!!

What you can do if you need an address of non-constant cast constructor? You need to declare an auxilary variable. For example, declare one SCR_RECT variable, say myScr,
SCR_RECT myScr;
and instead of
ScrRectFill (&(SCR_RECT){{a, b, c, d}}, ScrRect, A_XOR);
use:
myScr = (SCR_RECT){{a, b, c, d}};
ScrRectFill (&myScr, ScrRect, A_XOR);
Note that '&myScr' is legal, because 'myScr' is an lvalue (it is an ordinary variable). I hope that this helps a lot understanding of cast constructors and lvalues.

Q: I would like to make my own window but I don't understand the lot of fields in the WINDOW structure, like 'TaskID' and others!
A: You do not need to fill up the WINDOW structure manually: function WinOpen will fill everything automatically. See the next question for examples of usage.

Q: I need some examples of how to use the functions in the wingraph.h header file. Especially, I am confused with static and/or dynamic data allocation. I tried to use alloc.h to create necessary structures, but something was wrong...
A: I will give five very similar examples how to do the same thing. From first and fifth example you will see that you need not to use alloc.h at all, and in second, third and fourth example, you will see what you need to do if you want to use dynamic allocation (i.e. alloc.h) anyway. Maybe this is not so obvious from my documnetation, but flags in WinOpen must be ORed, so they must be "separated" by "|", not by commas.

Example 1: Using wingraph.h without dynamic allocation:
#include <wingraph.h>
#include <kbd.h>

int _ti89;

void _main (void)
{
  WINDOW wind;
  WIN_RECT winr = {20, 20, 80, 50};
  int result;
  WinOpen (&wind, &winr, WF_SAVE_SCR | WF_TTY);
  WinActivate (&wind);
  WinFont (&wind, F_6x8);
  WinStr (&wind, "hello everyone");
  ngetchx ();
  WinClose (&wind);
}
Example 2: Window is allocated dynamically:
#include <wingraph.h>
#include <alloc.h>
#include <kbd.h>

int _ti89;

void _main (void)
{
  WINDOW *wind = HeapAllocPtr (sizeof (WINDOW));
  WIN_RECT winr = {20, 20, 80, 50};
  int result;
  WinOpen (wind, &winr, WF_SAVE_SCR | WF_TTY);
  WinActivate (wind);
  WinFont (wind, F_6x8);
  WinStr (wind, "hello everyone");
  ngetchx ();
  WinClose (wind);
  HeapFreePtr(wind);
}
Note that a synonimus for HeapAllocPtr and HeapFreePtr are malloc and free (like in ANSI C).

Example 3: Both "window" and "rect" are allocated dynamically:
#include <wingraph.h>
#include <alloc.h>
#include <kbd.h>

int _ti89;

void _main (void)
{
  WINDOW *wind = HeapAllocPtr (sizeof (WINDOW));
  WIN_RECT *winr = HeapAllocPtr (sizeof (WIN_RECT));
  int result;
  winr->x0 = 20; winr->y0 = 20;
  winr->x1 = 80; winr->y1 = 50;
  WinOpen (wind, winr, WF_SAVE_SCR | WF_TTY);
  WinActivate (wind);
  WinFont (wind, F_6x8);
  WinStr (wind, "hello everyone");
  ngetchx ();
  WinClose (wind);
  HeapFreePtr (wind);
  HeapFreePtr (winr);
}
Example 4: How to use MakeWinRect to avoid "winr":
#include <wingraph.h>
#include <alloc.h>
#include <kbd.h>

int _ti89;

void _main (void)
{
  WINDOW *wind = HeapAllocPtr (sizeof (WINDOW));
  int result;
  WinOpen (wind, MakeWinRect (20, 20, 80, 50), WF_SAVE_SCR | WF_TTY);
  WinActivate (wind);
  WinFont (wind, F_6x8);
  WinStr (wind, "hello everyone");
  ngetchx ();
  WinClose (wind);
  HeapFreePtr (wind);
}
Example 5: This is what I do in my programs:
#include <wingraph.h>
#include <kbd.h>

int _ti89;

void _main (void)
{
  WINDOW wind;
  int result;
  WinOpen (&wind, MakeWinRect (20, 20, 80, 50), WF_SAVE_SCR | WF_TTY);
  WinActivate (&wind);
  WinFont(&wind, F_6x8);
  WinStr (&wind, "hello everyone");
  ngetchx ();
  WinClose (&wind);
}
Instead of
MakeWinRect (20, 20, 50, 50)
you may even write
&(WIN_RECT){20, 20, 50, 50}
This will generate smaller code, but works only when all four coords are constants.

Anyway, don't forget to CLOSE a window before the exit. If you forget to do so, TI may crash later, when window manager tries to refresh a still active window which ceased to exist due to end of the program!

In general, I prefer static allocation instead of dynamic. It is good if you know in advance how many open windows you have in the program (this is often a case on TI). Dynamic allocation is the only method if you don't know in advance how many open windows you need (then, you can keep them in linked list). I don't think that there is so many usage of this on TI :-)

Q: I don't understand how to use DrawIcon. Do I need to use pICON?
A: If you want to draw an icon at 50,50 for example, do:
ICON i = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
...
DrawIcon (50, 50, &i, A_NORMAL);
Of course, change 1, 2, 3... to the real definition of the icon.

pICON is necessary only for using with icons which are dynamically allocated (forget it if you are not familiar with dynamic structures in C), like in:
pICON p = malloc (32);
...
// Here is a code which fill up the icon structure
...
DrawIcon (50, 50, p, A_REPLACE);
Look operator "&" in first example, it is omitted in second example. In fact, "&" converts a variable of ICON type to pICON type (in general, it converts any type to corresponding pointer type).

Q: I want to make a program which draw a lot of lines (for example which does some kind of 3D graphic). But, it seems that DrawLine function is not too fast for my purposes. What I can do?
A: Yes, TIOS drawing routines are not championes in speed. Note that really fast line drawing function may be written only in ASM. But don't underestimate the power of C: even in pure C it is possible to make better (read: faster) line drawing routine than TIOS routine. As a programming exercise, I started with one trivial line drawing routine, and tried to optimize it. What I got is the routine which is in general 3-4 times faster than TIOS DrawLine routine. In some special cases, TIOS routine may be faster (for example, TIOS routine handles special cases when the line is horizontal or vertical), but in general case (slope lines) my routine is much better. Maybe (and probably) it may be speed-optimized yet; this is a challenge for you. Here is the routine:
void DrawLineFast (short x1, short y1, short x2, short y2)
{
  short x = x1, y = y1;
  short dx = abs (x2 - x1), dy = abs (y2 - y1);
  short ystep = (y1 < y2) ? 1 : -1, pystep = 30 * ystep;
  short mov = dx ? 0 : -1;
  unsigned char *ptr = (char*)LCD_MEM + 30 * y + (x >> 3);
  short mask = 1 << (~x & 7);
  if (x1 < x2)
    while (x != x2 || y != y2)
      {
        *ptr |= mask;
        if (mov < 0) y += ystep, ptr += pystep, mov += dx;
        else
          {
            mov -= dy;
            if (++x & 7) mask >>= 1;
            else ptr++, mask = 0x80;
          }
      }
  else
    while (x != x2 || y != y2)
      {
        *ptr |= mask;
        if (mov < 0) y += ystep, ptr += pystep, mov += dx;
        else
          {
            mov -= dy;
            if (x-- & 7) mask <<= 1;
            else ptr--, mask = 1;
          }
      }
}
If you need line erasing or line inverting routine, replace '*ptr |= mask' with '*ptr &= ~mask' or '*ptr ^= mask' respectively.

Q: I wonder how I can simulate the indirection operator ('#') from TI-Basic in C programs...
A: Nothing similar to '#' indirection does not exist in any compiling language (like C). You need to re-express your minds to avoid this operator, for example using multiple if-else statements, or using arrays. Don't be afraid, C will process it 1000 times faster than TI-Basic process indirections.

Q: I need the C equivalent of the 'when()' function from TI-Basic.
A: This is simple:
when (condition, true_val, false_val)
is translated to C as
condition ? true_val : false_val
For example,
sign = x >= 0 ? 1 : -1;
Happy?

Q: Does any method exists for detecting hardware release of the TI-89 calculator?
A: Julien Muchembled suggests the following method:
unsigned long GetHardwareVersion ()
{
  unsigned long hwpb, *rombase;
  rombase = (unsigned long *)((*(unsigned long *)0xC8) & 0x600000);
  hwpb = rombase[65];
  return (hwpb - (unsigned long)rombase  < 0x10000 &&
    *(unsigned short *)hwpb > 22 ? *(unsigned long *)(hwpb + 22) : 1);
}
But, if you ask it for detecting hardware version before using of grayscale routines, you need not to do it because GrayOn routine now performs an autodetection by itself.

Q: How I can make a program which does not need any kernel (i.e. "nostub" program), but which is greater than 8K and which works on AMS 2.03 too (or, greater than 24K and which works on AMS 2.04 and AMS 2.05 too)?
A: In fact, you need to made a short program (so-called "launcher") which will call the main program, bypassing the TIOS (to skip the software protection). Let the main program is "example.c". I recommended the following "launcher" (named "example2.c"):
#include <tigcclib.h>

int _ti89, _ti92plus;

#define fatal(s) {ST_showHelp (s); return;}

void _main (void)
{
  char *fptr, *cptr;
  unsigned short plen;
  SYM_ENTRY *SymPtr = DerefSym (SymFind ($(example)));
  if (!SymPtr) fatal ("Program not found");
  plen = *(short*)(cptr = fptr = HLock (SymPtr->handle)) + 3;
  if (SymPtr->flags.bits.archived)
    {
      if (!(cptr = malloc (plen)))
        {
          HeapUnlock (SymPtr->handle);
          fatal ("Out of memory");
        }
      memcpy (cptr, fptr, plen);
    }
  enter_ghost_space ();
  EX_patch (cptr + 0x40002, cptr + plen - 2);
  ASM_call (cptr + 0x40002);
  HeapUnlock (SymPtr->handle);
  if (cptr != fptr) free (cptr);
}
If you are not an expert, use this program as-is.

For anybody which want to know more about 8K limit: on HW1 calcs it is pure software limit, which can be broken by intercepting some error traps (used in DoorsOS and UniOS), or by making a short launcher which relocates called program and jump to it bypassing TIOS check. This is what I used. But, yet another problem must be solved: HW2. Namely, it has built-in a hardware device which does not allow that PC can be out of certain zone, so the launcher itself will not help. This device can't be turned off normally by software, but Julien Muchembled found a "hole" in the protection system which allows turning out this damned device (this is what his HW2 patch does): this is a very nasty method, and I don't want to explain this here. But, this protection device can be simply fooled: it protects only the "normal" RAM address space (i.e. first 256K of RAM). As RAM is partially decoded, address x and x+256K are the same for TI-89, but if you jump to x+256K instead of x, the protection will not be activated! Look to the launcher to see how it works, and you now can understand why I added 0x40000 (i.e. 256K) to addresses on two places. First, I relocate the called program as it is located on x+256K instead of x, then I call subroutine on x+256K instead of x.

AMS 2.04 and AMS 2.05 introduces yet another level of protection: with them, even jumping to the "ghost address space" (above 256K) is not possible if the program counter is out of certain area (this caused so-called "second launch crash"; if you have AMS 2.05 with any longer program like TI-Chess, you probably know what I am talking about). That's why I introcuced a new function called enter_ghost_space: its only purpose is to bypass smoothly this new protection!

Q: Is there any way to execute a file (i.e. another ASM or TI-Basic program) from a C program?
A: There are a lot of methods for doing this (see also previous question for a bit advanced example). The most obvious method to do this is usage of a function like this one:
short progrun (char *name)
{
  char fname[25];
  HANDLE h;
  TRY
    strcpy (fname, name);
    strcat (fname, "()");
    push_parse_text (fname);
    h = HS_popEStack ();
    NG_execute (h, FALSE);
    HeapFree (h);
  ONERR
    return FALSE;
  ENDTRY
  return TRUE;
}
The usage of it is straightforward, for example:
progrun ("testprog");
It will return FALSE in a case of error, else it returns TRUE. If you understand this function, you can easily expand it to accept arguments, etc. Principally, using NG_execute you can execute any particular sequence of TI-Basic statements.

Q: Does any function exists to find out how many folders are on the calculator and what files are in them? In other words, is there a way to get an array of all the folders on the calculator or an array of all the files in a folder?
A: This was very frequent question, but you can find the answer by reading carefully info about SymFindFirst and SymFindNext. And, look the example about returning values to TI-Basic given on the main page of this documentation. Mail me if still not clear...

Q: How I can determine the size of a symbol (i.e. TI-Basic variable) and the TIOS type of the variable?
A: Assume that you found a VAT symbol entry for a symbol (say symbol named "foo") which may be done for example using SymFindPtr:
SYM_ENTRY *sym;
...
sym=SymFindPtr($(foo), 0);
Then, do the following to find the size and type:
unsigned short size;
unsigned char type;
...
size= *(unsigned short*) HeapDeref (sym->handle) + 2;
type= *(unsigned char*) HToESI (sym->handle);
After this, variables 'size' and 'type' will contain exactly what do you want.

Q: I don't understand how to copy a symbol (TI-Basic variable) from one folder to another. As I can see, SymCpy doesn't copy the entire symbol, just the name!?
A: Moving symbols is quite easy (using SymMove), but copying is not so straightforward. Principally, you need to create a new one, and to copy the content of the original one into a new one. Fortunately, some users tells to me that it is possible to use function cmd_copyvar which executes just command CopyVar from TI-Basic. This function is still in unknown.h and will stay there for a while (I have some reasons for doing so), but the usage of it is quite obvious:
cmd_copyvar ($(var1), $(var2));
As it is TI-Basic call, it is highly recommended to execute it under TRY...ONERR...ENDTRY block.

Q: Is there a way to use TI89's Lists or Matrix, so I will be able to keep information like high score or something else...
A: Yes, more info about this can be found in this release of TIGCCLIB documentation (note that a matrix is "list of lists"). However, using lists or matrices is somewhat complicated. It is much easier to keep information in strings. Now, stdio.h header file is implemented which supports ANSI C compatible file handling, so file creating is quite simplified. In the documentation about this header file, an example is given about how to store information in a string. If you want to bypass stdio.h and to use low-level TIOS routines (such approach leads to smaller programs), see about SymAdd function and about organization of strings variables on doors.ticalc.org. To learn more about low-level VAT access, you can analyse my program scott.c or tichess by Thomas Nussbaumer, both of them read and write information in the strings.

Q: Is it possible to create a file which will have a custom type (i.e. which does not appear in VAR-LINK as a stanard type like STR, PIC, PRGM etc.). For example, I want to create a highscore file which will appear in VAR-LINK as HSC type...
A: Christian Walther pointed to me that this is possible. Moreover, this is easy. All you need to do is to create a file of "other" type (i.e. which terminates with OTH_TAG). TIOS then expects that a real type name is stored just below OTH_TAG as a zero-started zero-terminated string of maximum 4 chars. Look the following code fragment as an example:
FILE *fp = fopen ("example", "wb");
// store anything you want in the file here
fputc (0, fp);
fputs ("HSC", fp);
fputc (0, fp);
fputc (OTH_TAG, fp);
fclose (fp);
After this, you will have a file named "example" with type "HSC": you will see it in VAR-LINK...

Q: I want to avoid standard ANSI C functions for file handling like fopen etc. and to use low-level functions from vat.h (to make my program shorter), but I am not very sure what I need exactly to do to create a new file, and how I can manipulate with it.
A: Principally, to create a file you need to do the following:
  1. Create a new VAT symbol using SymAdd;
  2. Allocate a space for the variable using HeapAlloc;
  3. Dereference the symbol to get a pointer to the VAT entry, then store the handle returned by HeapAlloc to it;
  4. Put the actual file length in first two bytes of allocated space.
To be more concrete, I will show here a simple demo program which creates a string file (I use this internally), but it is easy to adapt to any file type:
#include <alloc.h>
#include <vat.h>

int _ti89;

HANDLE CreateFile (char *FileName)
// Returns a handle, H_NULL in case of error
{
  HANDLE h;
  SYM_ENTRY *sym_entry;
  char str[30], *sptr = str;
  *sptr = 0; while (*++sptr = *FileName++);
  if (!(h = HeapAlloc (HeapMax ()))) return H_NULL;
  if (!(sym_entry = DerefSym (SymAdd (sptr))))
    {
      HeapFree (h);
      return H_NULL;
    }
  *(long*) HeapDeref (sym_entry->handle = h) = 0x00010000;
  return h;
}

void AppendCharToFile (HANDLE h, unsigned char c)
{
  char *base = HeapDeref(h);
  unsigned short len = *(unsigned short*)base;
  if (len > HeapSize(h) - 10) return;
  *(unsigned short*)base = len + 1;
  base[len+2] = c;
}

void AppendBlockToFile (HANDLE h, void *addr, unsigned short len)
{
  unsigned short i;
  for (i = len; i; i--) AppendCharToFile (h, *((char*)addr)++);
}

void CloseFile (HANDLE h)
{
  AppendCharToFile (h,0); AppendCharToFile (h,0x2D);
  HeapUnlock (h);
  HeapRealloc (h, *(unsigned short*)HeapDeref(h) + 3);
}

void _main(void)
{
  static char s[] = "Hello world!";
  HANDLE h;
  h = CreateFile ("example");
  AppendBlockToFile (h, s, 12);
  CloseFile (h);
}
Note that used method is not the best: it initially allocates as many space as avaliable, then relocates the space on necessary size on closing, but it is worth to look on it. Note also that CreateFile function may be even simpler if you want to use it using CreateFile($(example)) instead of CreateFile("example"), i.e. if you avoid usage of ANSI strings.

Q: I have problems with making a program for communication between two calculators. For example, I can't seem to get data to consistantly transfer over the calc to calc link using calls from link.h. I wrote a simple program that just reads key presses and sends them as bytes while checking for bytes from the other calc. Strangely, it only gets about one byte for every 20 or so keypresses...
A: Many people tells to me about various problems (smaller or greater) with link.h. See the answer about the question why the function ngetchx is slow. Maybe this will help you. I must tell that the linking is not so known topic for me... You must ask some link guru if you want to know more about this problematic...

Q: The documentation about menus.h says (cite): "Although TIOS menu system allows menus with more than one level of submenus, it is not possible to create such menus using this command (PopupAddText)". What happens then? And how it is possible to make menus with more levels of submenus?
A: The answer of the first part of the question is: just nothing. Options which are added on deeper levels are just ignored. When I dissasembled this routine, I find that this is really not implemented! About the second part of the question: this is answered in the documentation about menus.h header file in this release of TIGCCLIB.

Q: The popup menu given in the example for menus.h seems to work fine on its own, but not when used in a dialog: if you select anything after "Option 2" the text in the selector is the wrong one. Can't dialog popups handle sub-menus?
A: I am afraid that popups in dialogs can't have sub-menus. I think so because I never see on TI-89 any system dialog which has such popups. Yes, it sucks, but this is not my guilt...

Q: The documentation about MenuPopup says that it ss possible to make popup menus by picking up bytes with the VTI debugger to save the memory, but I don't know how to do this. Could you tell me how to do this please?
A: Not so easy to explain if you are not experienced user. Basically, after you define a menu using PopupNew, PopupAddText etc. you need to display its address instead of executing it. E.g. instead of doing
PopupDo (handle,...)
you need to do something like:
printf_xy (0, 50, "Address=%lx", HeapDeref(handle));
ngetchx();
Then, while waiting for a keypress, open a VTI debugger, and go to the displayed address. Take a pencil and write a sequence of bytes starting from this address. Tenth and eleventh byte in this sequence will tell to you how many bytes you need to pick. After this, put these bytes in the array, and pass such array as an argument to the MenuPopup function. As an exercise, try this on an example given in the documentation.

Q: Is it possible to write a program which will return a value to TI-Basic, i.e. which acts like functions in TI-Basic?

Starting from TIGCCLIB 1.5, this is very easy, and described on the starting page of TIGCCLIB documentation.

Q: What is wrong in doing
a = GetIntArg (top_estack);
It seems that it works fine, but you always use an auxilary variable...
A: It works fine sometimes, but not always. See, GetIntArg is a function-looking macro, with changes the value of its actual argument. So, if you write
a = GetIntArg (top_estack);
you will also change the value of TIOS system variable top_estack, and I am not sure that you really want this. So, I strictly recommend using an auxilary variable, like in the following example:
ESI argptr = top_estack;
...
a = GetIntArg (argptr);
Using this method, you will avoid unexpected changes of top_estack.

Q: I have a matrix on the top of the expressions stack which is produced as a result of calculation, and I don't know how do I put a matrix element located at [i,j] into result (values of 'i' and 'j' may vary)? I have read infos about estack.h, but I couldn't find the answer...
A: There is a lot of methods. I suggest the following one:
ESI ptr;
int result;
int i = 1;                             // Just an example
int j = 2;
push_parse_text ("[[11,12][21,22]]");  // An example matrix
ptr = locate_element (i,j);
result = GetIntArg (ptr);              // (assumed that elements are ints)
where 'locate_element' is an user-written function, which may be implemented as follows:
ESI locate_element (short m, short n)
{
  short i;
  ESI ptr = top_estack-1;
  for (i = 0; i < m-1; i++) ptr = next_expression_index (ptr);
  ptr--;
  for (i = 0; i < n-1; i++) ptr = next_expression_index (ptr);
  return ptr;
}
You can use it as-is, but it will be much better if you can understand how it works.

Q: Suppose I'm writing an ASM function 'foo(n)' which accepts an argument (a string, for example). I want to make 'foo(n)' return 'foo(n)' (the call itself) when 'n' is of type "VAR" (i.e. if nothing has been assigned to 'n' yet)...
A: This is quite easy, if you know in advance the name of the program. Suppose, that your program name is "foo". Here is the demo which will return 'foo(n)' when you type 'foo(n)' if 'n' is the variable, and which will return the string "blabla" (for example) when the argument is anything else:
#define RETURN_VALUE
#include <tigcclib.h>

int _ti89;

void _main (void)
{
  ESI argptr = top_estack;
  if (GetArgType (argptr) <= VAR_Q_TAG)  // it means that arg is "VAR"
    {                                    // see Tags to see why...
      push_string ($(foo));
      top_estack--;                      // Necessary to replace STRING_TAG
      push_quantum (USERFUNC_TAG);
    }
  else push_string ($(blabla));
}
Note that this solution is not ideal: if you rename the program name to "huh" instead of "foo", then call 'huh(n)' will return 'foo(n)' instead of 'huh(n)', due to statement 'push_string($(foo))'. It IS possible to determine the real name of the program in the run time, but this is very awkward.

Q: I need to know more about how does the TIOS store and reference big integers? In other words, what would be the C structure that would be used to represent any arbitrarily-long binary integer? In addition, I am particularly interestad about how would two extermely long binary integers be multiplied and divided? Does TIOS have its own binary multiplication routine somewhere in the ROM? Something that works similarly to BCD multiplication/division, I'm guessing?
A: TIOS store all integers (both small and large) in the following format (looking from lower to higher addresses):
  1. Bytes of the integer in little endian (up to 255 bytes);
  2. The number of bytes occupied by integer (one byte);
  3. POSINT_TAG or NEGINT_TAG, depending of the sign.
These integers are kept on the expressions stack, or in TI-Basic variables (of course, in TI-Basic variables, there are two extra bytes at the begining, which represents the length of a variable). In other words, integers are kept in a structure which is similar like BN structure defined in rsa.h header file, except the length byte is at the end, not at the begining (because data on the expressions stack is always in RPN). So, such structure can't be strictly represented using a valid C syntax, because it requires something as
struct big_int
  {
    BYTE data[size];   // but 'size' is not known in advance
    BYTE size;
    BYTE tag;
  }
Routines for multiplying and dividing very long integers surely exist in the TIOS, but the strange fact is that such routines are not in TIOS jump table (read: they are not usable). Anyway, you can always use a general eveluating routines like NG_rationalESI and NG_approxESI. For example, to multiply two very-long-integers, you can use the following template:
push two very-long-ints on the estack
push_quantum (MULT_TAG);
NG_approxESI (top_estack);
However, two routines for working with long integers are in TIOS jump table: for calculating '(A*B)%N' and '(A^B)%N' where "%" is "modulus" operation, and "^" is "raising to a power". These operations are used in RSA cryptosystem. Both of them are defined in rsa.h header file. They may be used for multiplying and raising to the power: you always can set N to very a big number, then (A*B)%N = A*B. Also, you can use them for calculating modulus (if you set B to 1). But, I am not sure how you can simulate division. I think that TI never use integer division: everything like 'A/B' is kept as a fraction, except in approx mode; TIOS then uses NG_approxESI.

Q: In addition to functions from stdio.h header file, I need gotoxy function to allow porting some PC programs to TI...
A: All printing functions from stdio.h are sensitive to MoveTo command, so it is not hard to set print position to anywhere. If you need just gotoxy, it is impossible for 4x6 font, because it is proportional. But, for 6x8 and 8x10 fonts, it may be implemented trivially:
#define gotoxy(x,y) MoveTo (6*x-6,8*y-8)    // for 6x8 font
#define gotoxy(x,y) MoveTo (8*x-8,10*y-10)  // for 8x10 font
Here I assumed that top-left corner is (1,1) as on PC. Note that you MUST NOT put a space between gotoxy and left bracket (else the preprocessor will define an argument-less macro). You can also define an universal gotoxy macro which will work regardless of current font setting, using smart GNU C macros:
#define gotoxy(x,y) \
  ({short __f=2*FontGetSys(); MoveTo((4+__f)*(x-1),(6+__f)*(y-1));})
You will not be able to understand this if you are not familiar with GNU extensions.

Q: When I'm using printf function, I'm not abble to reset the scrolling: after using this function, and after clearing the screen, the text is still displayed at the bottom of the screen, even if the calculator was turned off between two use of the program... How can I reset the scrolling?
A: As I know, I warned in the documentation that ClrScr and clrscr are not the same: the second one resets the print position too, so you need to use it. Anyway, you can always use MoveTo to reset print position to (0,0) which effective resets the scrolling.

Q: How I can get an input from the keyboard?
A: There is a lot of method how you can make such routine. This is quite easy if you are a C programmer. The easiest but the worst method is to use gets function from stdio.h header file: gets does not allow any editing facitilities (even backspace key will not work). It may be useful while the program is in a testing state. It is recommended in any serious program to make a custom keyboard input routine. For example, I usually used the following routine, which is good enough for many purposes:
void InputStr (char *buffer, short maxlen)
{
  SCR_STATE ss;
  short key, i = 0;
  buffer[0] = 0;
  SaveScrState (&ss);
  do
    {
      MoveTo (ss.CurX, ss.CurY);
      printf ("%s_  ", buffer);
        // Note that two spaces are required if F_4x6 font is used
      key = ngetchx ();
      if (key >= ' ' && key <= '~' && i < maxlen) buffer[i++] = key;
      if (key == KEY_BACKSPACE && i) i--;
      buffer[i] = 0;
    } while (key != KEY_ENTER);
}
Especially, if very good editing facitilities are required, the best idea is to use routines from textedit.h header file. These routines are extremely powerful and fully customizable. Alternatively, you can also use routines from dialogs.h, especially DialogAddRequest.

Q: Did you find the keyboard input function that gets called when you do an InputStr in TI-Basic? I'm looking at GKeyIn as probably the main part of whatever this function is, but it also includes the ability to bring up the CHAR dialog, look up key equivalents, and lots of other nice stuff that I want to be able to use.
A: TIOS function cmd_inputstr just performs InputStr command from TI-Basic, but this function is rather limited in pratcice that it is better to made a similar function by yourself, i.e, it IS possible to call it, but there is a lot of artefact in doing it. See also the previous and the next question.

Q: I really need a routine like InputStr given above, but which is able to bring up the CHAR dialog. However, I am not able to make such routine by myself...
A: I received a lot of such questions. These questions are usually asked by newbie programmers, but the answer is quite advanced. Although I don't like to present advanced routines as-is without a lot of necessary explanations, I am requested to do so. Well, here is a routine:
void InputStr (char *buffer, short maxlen)
{
  SCR_STATE ss;
  short key, captured, i=0;
  void CaptureHandler (EVENT *ev)
    {
      if (ev->Type == CM_STRING)
        captured = *(ev->extra.pasteText);
    }
  buffer[0] = 0;
  SaveScrState (&ss);
  do
    {
      MoveTo (ss.CurX, ss.CurY);
      printf ("%s_  ", buffer);
        // Note that two spaces are required if F_4x6 font is used
      key = ngetchx();
      if (key == KEY_CHAR && i < maxlen)
        {
          EVENT ev;
          ev.Type = CM_KEYPRESS;
          ev.extra.Key.Code = key;
          EV_captureEvents (CaptureHandler);
          EV_defaultHandler (&ev);
          EV_captureEvents (NULL);
          buffer[i++] = captured;
        }
      if (key >= ' ' && key <= '~' && i < maxlen) buffer[i++] = key;
      if (key == KEY_BACKSPACE && i) i--;
      buffer[i] = 0;
    } while (key != KEY_ENTER);
}
It will be good if you can understand how it works (I recommend reading the documnetation for the events.h header file). Note that this example use one not-so-known GNU C extension: nested functions (CaptureHandler is define inside InputStr). This feature is well-known in Pascal, and I used it just to encapsulate whole routine into one function, and to avoid usage of global variables (else, captured would have to be global).

Q: I have problems with OSGetStatKey function.
A: See what I wrote about this in the documentation about kbd.h header file. I recommend usage of pseudoconstants from compat.h header file instead.

Q: Is there any way for reading the keyboard faster than using ngetchx function, but without very low-level access using _rowread? In ASM programs under DoorsOS, I usually read kb_globals, but is it possible to do something similar with TIGCCLIB?
A: Yes, there is a LEGAL method to pick keystrokes directly from the keyboard queue. See kbd_queue and other queuing functions from system.h header file.

Q: Reading directly from the keyboard queue is a good idea, but the key repetition feature does not work...
A: On the first look, it seems that the key repetition feature really does not work with OSdequeue. But, Marcos Lopez informed me that this is not exactly true. Key repetition feature works even with OSdequeue, but it will not return the keycode itself for the repeated key, but sets an additional bit in the keycode, so value becomes value + 0x800. If you use standard ngetchx function, this additional bit is masked out and your program will get the keycodes it expects. But, it is very simple to mask out this bit manually and make the key repetition feature working even with OSdequeue.

Q: Why functions ngetchx and kbhit are so slow?
A: They also implements support for Silent Link feature (ability of automatic receiving programs when the calculator is in Home Screen). That's why they may also interfere with the link transfer!

Q: I have a lot of troubles while reading I/O ports. I need a loop which will wait until the programable timer on the TI-89 reaches value 255. I know that I can read the value of the programable timer counter using address 0x600017, so I made the following loop:
while (*(unsigned char *)0x600017 != 255);
But, the calculator freezes. I tried to use peek macro, as in
while (peek (0x600017) != 255);
No fortune again (I know that this is, in fact, the same as above). What is wrong?
A: See, there is a problem when reading I/O ports in small loops. Look the above loop for example. T1he compiler will notice that the same value is read again and again in the loop. As normal memory location can not be changed without explicite writing to it, and there is nothing in the loop which changes address 0x600017, the optimizer will move memory reading out of the loop to make the code more efficient. Such behaviour is correct for ordinary memory locations. But, in our case, it will cause an infinity loop. The compiler does not know anything about the fact that 0x600017 is not an ordinary memory location but an I/O port, which may be changed unpredictably (purely by the hardware, without any program control). To prevent such behaviour, you should use a volatile keyword to make an address 'volatile', i.e. to say to the compiler that this address may be changed unpredictably. So, the correct code is
while (*(volatile unsigned char *)0x600017 != 255);
Starting from TIGCCLIB 2.3, a new macro peekIO is introduced, to make life easier. You can do
while (peek (0x600017) != 255);
Basically, peekIO works exactly like peek, but prevents any unwanted optimizations generated by the compiler. Always use peekIO (or peekIO_w)for reading memory-mapped I/O ports, else you may have troubles. _rowread function in TIGCCLIB releases prior to 2.3 also caused similar troubles, now this is corrected too.

peekIO may be used even for reading bytes into the memory, but peek will generate better code when working with memory. However, use peekIO to read any memory location which may change on a way which is unpredictable from the aspect of a normal program flow (for example, a memory location which is changed in the body of the interrupt handler).

NOTE: For sending bytes to I/O ports, macros pokeIO and pokeIO_w are also introduced, which are more reliable for this purpose than poke and poke_w.

Q: What is the true equivalent for DoorsOS idle_loop function?
A: GKeyIn (NULL, 0) is the most similar equivalent. ngetchx () is not so similar. Both functions are defined in kbd.h. Note that idle defined in system.h is NOT equivalent to idle_loop!

Q: How to bring up the VAR-LINK dialog from C code and then get the name of the file that was selected?
A: This is an advanced question. As VAR-LINK dialog is event-driven applet, you must need use an event-driven functions defined in events.h header file. Bringing up the VAR-LINK dialog is quite easy:
EVENT ev;
ev.Type = CM_KEYPRESS;
ev.extra.Key.Code = KEY_VARLNK;
EV_defaultHandler (&ev);
but getting the name of the file that was selected is a bit harder. After executing of VAR-LINK dialog, VAR-LINK applet will send the name of the selected file to the current application via CM_HSTRING message. This message may be captured by an user event handler. Here is the demonstration program:
#include <tigcclib.h>

int _ti89;

char VarBuffer[20] = "";

void VarLinkHandler (EVENT *ev)
{
  if (ev->Type == CM_HSTRING)
    strcpy (VarBuffer, HeapDeref (ev->extra.hPasteText));
  EV_defaultHandler (ev);
}

void VarLinkDialog (void)
{
  EVENT ev;
  EVENT_HANDLER OldHandler = EV_captureEvents (VarLinkHandler);
  ev.Type = CM_KEYPRESS;
  ev.extra.Key.Code = KEY_VARLNK;
  EV_defaultHandler (&ev);
  EV_captureEvents (OldHandler);
}

void _main(void)
{
  VarLinkDialog ();
  printf_xy (0, 50, "You picked: %s", VarBuffer);
  ngetchx ();
}
Read more about events.h header file: incredible miracles may be produced using event passing technics!

Q: What is wrong in calling the previous installed event handler in a new one? Whenever I tried to do so, my only result is a crash...
A: Very probably you do
OldHandler = EV_captureEvents (NewHandler);
then you call OldHandler from NewHandler. There would be nothing wrong in doing so, but function EV_captureEvents returns NULL when there is no any user handlers previously installed, which is very common case. So, you can call OldHandler only if it is not null. In other words, it is illegal to call an event handler when it is not actually installed. From the other side, function EV_defaultHandler calls the TIOS handler which is used for default dispatching of some common events. It works independently of which handler is currently installed and whether it is installed at all. This is a function which you probably need to call in your event handler to process all unprocessed events.

Q: I don't understand how I can use functions from textedit.h header file to edit a text variable. When I tried to open a blank editor everything seems OK, but when I tried to edit an existing text variable, I got a crash...
A: I must admit that the problem is not so easy. The problem is, in fact, caused by severe error in my documentation in releases of TIGCCLIB prior to 2.2 (it is corrected now). Namely, I was wrong when I told that a handle passed as a parameter to TE_open function may be a handle of a text variable. In fact, text variables have another extra data at the begining (one word for the length, and one word for the cursor position). But, the editor expects a raw data. I inspected what TIOS does exactly during opening a text variable. Then I concluded: there is no any other solutions than striping out extra data (this is a little play with memmove). Of course, after the editing is finished, it is necessary to reconstruct again the proper structure of the text variable (this is possible using some informations presented in TEXT_EDIT structure after the editing is finished).

After this theoretical elaboration, I will be much more concrete. Here is a complete code which edits the text variable named 'mytext'. Due to simplicity, it is assumed that this variable really exists and that it is not archived:
#define SAVE_SCREEN

#include <tigcclib.h>

int _ti89;

TEXT_EDIT te = {};   // An empty initializer

void EventHandler (EVENT *ev)  // Typical event handler for text editing
{
  if (ev->Type == CM_KEYPRESS && ev->extra.Key.Code == KEY_ESC)
    ER_throwVar(1);
  if (!TE_handleEvent (&te, ev))
    EV_defaultHandler (ev);
}

void _main ()
{
  char *base_addr;
  SYM_ENTRY *sym = SymFindPtr ($(mytext), 0);

  if (!sym) return;  // Exit if file not found...

  // First, you need to remove the garbage data at the begining of
  // the text variable, because the text editor expects a raw data:

  base_addr = HeapDeref (sym->handle);
  memmove (base_addr, base_addr + 4, peek_w(base_addr));

  // Now, do the editing. This is straightforward...

  WinClr (DeskTop);
  TE_open (&te, DeskTop, MakeWinRect (0, 16, 159, 92), sym->handle, 1, 0, 7);
  CU_start ();
  EV_captureEvents (EventHandler);
  TRY
     EV_eventLoop ();
  ONERR
     EV_captureEvents (NULL);
  ENDTRY

  // Finally, you must transform raw editor data into the proper
  // format of the text variable. This is not so straightforward:

  base_addr = HeapDeref (HeapRealloc (sym->handle, te.CurSize + 10));
  memmove (base_addr + 4, base_addr, te.CurSize);
  poke_w (base_addr, te.CurSize + 4);
  poke_w (base_addr + 2, te.CursorOffset);
  poke (base_addr + te.CurSize + 4,0);
  poke (base_addr + te.CurSize + 5, TEXT_TAG);
}
It is important to understand how this program works if you planed to do any serious application of text editing functions.

NOTE: If you are very pedant, and if you enable a very strong level of warnings checking, the compiler will warn you about initializing a TEXT_EDIT structure with an empty initializer. If you don't like any warnings, the full initializer form is:
TEXT_EDIT te = {NULL, 0, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0}};
If you ask me, I am not so pedant.

Q: When I tried to create my own window to be used as a parent window for the text editor (instead of the DeskTop window), and when I passed an address of my window to TE_open, the editor goes blank (it does not display the file content on the screen, although the editing seems to work). What is wrong?
A: I was also very surprised when I noticed this. After some investigations, I concluded that the window passed to TE_open must not be "dirty" (i.e. it must not have WF_DIRTY flag set), but windows created by WinOpen are "dirty" by default. So, you need to clear "dirty" flag manually before calling TE_open. This is straightforward. For example,
WIN_RECT myRect = {0, 16, 159, 92};
WINDOW myWin;
TEXT_EDIT te;
...
WinOpen (&myWin, &myRect, WF_NOBORDER);
myWin.Flags &= ~WF_DIRTY;
TE_open (&te, &myWin, &myRect, ...);
Anyway, there is no strong reasons to use any windows other than DeskTop as a parent window, except if you want to use the whole screen for the editing area (the desktop window is clipped in the toolbar area). But, note that using whole screen for editing is not so good idea. The editor expects that the menu is on the top. So, if you press F1 etc. while doing "full-screen" editing, your screen will be trashed, because the editor will open the menu, and it will expect that the toolbar is at the top, etc. etc. Try to see. The solution? Disable all keys like F1, etc. in the event handler (e.g. do not pass them to TE_handleEvent) if you really want to do full screen editing...

Q: Is it possible to use any other font except 6x8 font in the text editor?
A: Principally, you can change font using WinFont before calling TE_open. For example, you can do
WinFont (DeskTop, F_8x10);
However, the editor will work fine with both 6x8 and 8x10 fonts, but not with 4x6 font (try and see), because it is proportional, so the editor will be fooled (editors usually expects fixed-size fonts). This is a pity.

Q: When I tried to use sizeof operator to determine the exact size of some objects, I got zero as the result. What is wrong?
A: You probably tried something like
printf ("%d", sizeof (something));
ANSI standard proposes that sizeof operator returns a value of type size_t, which is in fact long integer in this implementation. So, the result is pushed on the stack as a long integer, but format specifier "%d" expect an ordinary integer, so it pulls from the stack just one word, which is zero in this case. You need to write
printf ("%ld", sizeof (something));
Alternatively, you can use the typecast to convert the result to a short integer
printf ("%d", (short) sizeof (something));
assuming that no object would be longer that 32767 bytes.

Q: Is it possible to determine the size of the function using the sizeof operator?
A: No. In "normal" programs you should never know this information. ANSI C even does not propose what is 'sizeof(function)', and such construction will be rejected by the most of C compilers. GNU C (like TIGCC is) uses extended pointher arithmetic on such way that 'sizeof(function)' is always 1. If you are a dirty hacker (as I am), and if you really need to determine the number of bytes occupied by function, I used the following method:
void MyFunction (void)
{
  // The function body...
}
void End_Marker(void);
asm("End_Marker:");
...
...
num_of_bytes = (char*)End_Marker - (char*)MyFunction;
Note however that this method is not absolutely reliable, because it depends of the ordering of functions in the program. But, the compiler is free to change the order of functions if such reorganization may lead to a better code.

Q: I need access to the archive memory...
A: This is implemented in this release. See flash.h header file.

Q: When I tried to use EM_moveSymToExtMem to archive a file, the calculator crashes!
A: You probably wrote something like
EM_moveSymToExtMem ("example", HS_NULL);
Instead, you need to write
EM_moveSymToExtMem ($(example), HS_NULL);
This routine except SymNames, not ordinary C strings. See SymFind and $ macro constructor in vat.h header file for more info.

Q: How do you make that the status line is not visible on the screen so that the status indicators do not mess up your graphics?
A: The most general method (I use this) is: disable auto-int 1 using OSSetSR function (status line indicators are updated from this interrupt). Note that in this case you need to read the keyboard using _rowread function, because ngetchx etc. are based on auto-int 1. I used this method in my program cblaster (you can pick it from ticalc).
Q: I'm writing a game in C, but I encountered the following problem: when I disable interrupts, the grayscale doesn't work...
A: Of course, because the grayscale is based on interrupts. I.e. you must not disable them in grayscale programs. So, what to do? You probably want to disable auto-int 1 to avoid screwing up the status line. Instead of DISABLING auto-int 1, you may REDIRECT it to nothing. New header file intr.h provides very elegant methods for doing this. It is enough to do this:
INT_HANDLER save_int_1;
...
save_int_1 = GetIntVec (AUTO_INT_1);
SetIntVec (AUTO_INT_1, DUMMY_HANDLER);   // redirect auto-int 1 to "nothing"
// enable grayscale
// do your code
// disable grayscale
SetIntVec (AUTO_INT_1, save_int_1);
This method is much more elegant than in previous releases of TIGCCLIB.
Q: I'm just fiddling around with interrupt handlers and don't understand why the following code won't work:
void myInterruptHandler (void)
{
  asm ("movem.l %d0-%d7/%a0-%a6,-(%sp)");
  // do something here...
  asm ("movem.l (%sp)+,%d0-%d7/%a0-%a6; rte");
}
 
A: There are two reasons for this. First, sequence "do something here" surely uses some local variables. The compiler will put them in the registers during the optimization, and it will generate code for saving them on the stack at the begining of the procedure, before execution of any statements in the function body. So, before executing
asm("movem.l %d0-%d7/%a0-%a6,-(%sp)");
something will be pushed on the stack. Read this as "open brace '{' is not only the marker, it also generates an entry procedure code". So, when "rte" is encountered, the return address on the stack is trashed. Second, even if the procedure does not use any local vars, entry code for the procedure is usually
link #something,%a6
and the stack is again not suitable for executing "rte". Before release 2.2 of TIGCCLIB, the only universal and correct method for defining interrupt handlers was is to define a pure assembly auxilary procedure as follows:
void InterruptHandler(void);  // Just a prototype
asm ("myInterruptHandler:
      move.w #0x2700,%sr
      movem.l %d0-%d7/%a0-%a6,-(%sp)
      jsr MainHandler
      movem.l (%sp)+,%d0-%d7/%a0-%a6
      rte");

void MainHandler(void)
{
  // Put everything you want here...
}
To make life easier, starting from release 2.2, I introduce a new language extension called DEFINE_INT_HANDLER in intr.h header file. Now, it is enough to write
DEFINE_INT_HANDLER (myInterruptHandler)
{
  // Put everything you want here...
}
Q: Maybe I am quite stupid, but I cannot catch anything about communicating information between the C code and the assembly code... I'm not really familiar with mixing high-level languages with assembly language; all I really know is that the asm keyword allows one to include assembly instructions in C source code. But how would would you write an assembly function that C code could utilize?
A: This is explained in details in this release of TIGCC documentation. See section about Extended Asm.

Return to the main index