![]() |
Breaking the 64KB Limit Using a DLL |
Breaking the 64 KB limit is an important topic, and because of the internal
representation of files in the AMS as well as the size limit of memory
blocks, it is possible only by breaking the program up into multiple files.
If you get close to this limit, the first thing to do is optimizing the
program. Ways to do this are those described in
Advanced Options of TIGCC, using functions from the AMS instead of
those from the TIGCC Library, and, last but not least, hand-optimizing the
code. If and only if you are still close to the limit, you should think about
the possibility to use multiple files. At first, try storing as much data as
possible (sprites, maps, etc.) in external files (using functions from
vat.h). If this still does not help, the only
possibility left is to split the code into multiple files.
This means that you need to use some form of dynamic link libraries. These
are very well-known for kernel programs, but kernel-mode libraries are not
something we want to encourage, seeing that they have led to a huge mess of
versioning problems and incompatiblities. For information about how to create
them, see the section How to make
kernel-based programs. Libraries for kernel-less programs are relatively
new (available in TIGCC starting from version 0.94); now that it is possible
to create them, the program code may in fact be arbitrarily large. The
necessary definitions can be found in the dll.h
header file.
Now that we have explained why you might need to use external libraries, we
specifically want to discourage their use for anything else. External
(dynamic) libraries have been used quite often in the past to automate common
tasks, like file access, graphics, compression, etc. This is not what
we want to happen, otherwise there will be a different libraries for the same
tasks, with a lot of incompatiblities between libraries and even between
different versions of the same library. TIGCC provides the possibility to use
static libraries (also known as function archives) for this purpose. In the
IDE, you need to select the creation of a
function archive in the project options; when using the
command line compiler, you need to use
the '-ar' switch. When using function archives, only the files which
are needed are really included in the final program.
There is an exception to the rule that you should not create a dynamic
library to make it available to others: If the library itself is very large,
and a program will typically use a lot of its functions at the same time,
client programs are likely to exceed the file size limit if it is provided as
a static library. In this case, using a dynamic library really is the only
possibility. An example is the FAT Library by the
TI-Chess Team.
Hopefully, we have talked you out of creating a dynamic library if there is
any other reasonable option. Now we can explain how to create a dynamic
library in nostub (kernel-less) mode. For detailed explanations of all
directives, take a look at the dll.h header
file. The "Custom DLL" example demonstrates the creation of a very small
library (note that the library file must have the name "mydll" on the
calculator):
// Custom DLL example; must be named "mydll" // Note: You should not use DLLs under normal circumstances; see section // "How to break the 64 KB limit using a DLL" for more information. #define USE_TI89 #include <tigcclib.h> DLL_INTERFACE char MessageInDLL[]="Hello!\n"; long GlobalVarInDLL; void HelloFromDLL(void); int SumFromDLL(int,int); DLL_ID 372377271 DLL_VERSION 2,12 DLL_EXPORTS HelloFromDLL,SumFromDLL,MessageInDLL,&GlobalVarInDLL DLL_IMPLEMENTATION void HelloFromDLL(void) { printf ("Hello from DLL!\n"); printf ("Global variable is %ld\n", GlobalVarInDLL); } int SumFromDLL(int a, int b) { return (a + b); }The order of the definitions is very important; read more about this in DLL_INTERFACE. The exported symbols are HelloFromDLL, SumFromDLL, MessageInDLL, and GlobalVarInDLL; they are assigned index numbers from 0 to 3.
#define USE_TI89 #define SAVE_SCREEN #include <tigcclib.h> #define HelloFromDLL _DLL_call(void,(void),0) #define SumFromDLL _DLL_call_attr(int,(int,int),__attribute__((stkparm)),1) #define MessageInDLL _DLL_reference(const char,2) #define GlobalVarInDLL _DLL_glbvar(long,3) void _main(void) { if (LoadDLL ("mydll", 372377271, 2, 11) != DLL_OK) { DlgMessage ("ERROR", "Error loading DLL!", BT_OK, BT_NONE); return; } clrscr (); GlobalVarInDLL = 1234567; HelloFromDLL (); printf ("Sum from DLL: 2+3=%d\n", SumFromDLL (2, 3)); printf ("Message from DLL: %s\n", MessageInDLL); ngetchx (); UnloadDLL (); }This program simply demonstrates all possible ways to import symbols from the DLL. See LoadDLL and the corresponding identifiers for more information.
EXECUTE_IN_GHOST_SPACE
needs to be defined at the beginning of the program. You will will want to
exepack the program anyway if it is large enough. In the
IDE, this can be done through a check box in
the project options; when using the
command line compiler, you need to use
the '-pack' switch.
NO_CALC_DETECT
helps
for calculator-dependent definitions, but not all parts of the TIGCC Library
are available (for example, defining
RETURN_VALUE
makes
absolutely no sense).