![]() |
FAT-Engine - SDK | (c) 2001/2002 TiCT |
How To Debug Client Programs using the FAT-Console |
Since beta version 1.05 the FAT-Engine is built in two different ways: Once with an integrated debugging console (FATLIB_C.DLL) and once without the console (FATLIB.DLL).
The version with the integrated console (FATLIB_C.DLL) SHOULD BE USED ONLY for debugging your programs during development. PLEASE don't distribute it with your programs. Distribute FATLIB.DLL instead!
To use the console version of the engine make sure you have deleted file fatdll.lib and that you have uploaded file fatdll_c.lib to your calc.
If you start now a FAT game, press the console hotkey ([4],[5] and [6] pressed simultaneously) to bring up the FAT console instead of the FAT window. If this won't happen and your game "freezes" you are probably using a game with client doublebuffering. Just press [ESC] in this case and the game will continue as usual. Normally this shouldn't happen, because IMO using additionally doublebuffering on the client's side make no sense.
Internally the FAT-Console uses _rowread() to query the keyboard. For proper work of the FAT-Console a FAT client game should redirect AutoINT-1 and AutoINT-5 like the demo programs do.
When everything goes right you should see now the FAT-Console displaying the data of the active FATCONFIG. By pressing [UP] and [DOWN] you can cycle through the different info sections of the console. By pressing [LEFT] and [RIGHT] you can cycle through the different pages of the actual info section. Key [ESC] will close the console.
In general there are 4 different information sections:
The ENGINE section displays informations about the engine (version number, builddate etc.).
- ENGINE section
- FATCONFIG section
- SPRITE section
- CLIENTSLOT section
The FATCONFIG section will display informations about the active FATCONFIG which gots handed over to FAT_Render() by the client program.
If the program uses no sprites yet (FATCONFIG.nr_sprites==0), the SPRITE section will not be displayed (clear, isn't it?). Otherwise you will see the data of the first sprite. By using [LEFT] and [RIGHT] you can cycle through the complete sprite list.
And last, but not least there is the CLIENTSLOT section. In this section up to 70 variables specified by the client program itself can be displayed. You can use [LEFT] and [RIGHT] to cycle through the pages of this section. If a program specifies no parameters these pages will be empty.
The CLIENTSLOT section is the most useful section within the FAT-Console. The sourcecode of a program can be instrumented with function calls which adds variables to this list. When you open the console you can examine the current value of this variable. A simple program which specifies own variables to be displayed in the console may look like this:
#define FAT_USEDEBUG // set this define to enable debugging #include... ... unsigned short counter = 0; unsigned char* plane = GetPlane(LIGHT_PLANE); ... ... FAT_DebugUseSlot(0,"mycounter",&counter,FAT_DBG_USHORT_DEC); FAT_DebugUseSlot(1,"lightplane",&plane,FAT_DBG_LONG_HEX); // IMPORTANT: pointer of pointer variable! ... ... while (!(FAT_GetPadState() & KEYPAD_ESC)) { FAT_Render(&fc); counter++; } ... ...
The first line is very important. Without the FAT_USEDEBUG define will NOT FAT_DebugUseSlot() produce any code. Therefore you can leave the FAT_DebugUseSlot() calls in the sourcecode. Just uncomment the define and no additionally code will be generated.
FAT_DebugUseSlot() takes 4 parameters. The first parameter is the slotnumber (0..69) which you want to use. The second parameter is a string which is displayed as variable name in the console. Make sure that this string is not very long. Otherwise the display gets corrupted.
The third parameter is a pointer to the variable you want to trace. Even if the variable is already a pointer you will have to add the "&" sign in front of it!
And the last parameter specifies the formatting which should be used by the console to display the variable. All format specifying macros start with FAT_DBG_ than comes a type (CHAR,UCHAR,SHORT,USHORT,LONG,ULONG) and last comes _DEC or _HEX (decimal or hexadecimal display). There is only macro which differs from the above naming convention: FAT_DBG_STRING - this macro can be used to tell the engine that the given pointer points to a string variable.
If you want to clear a debug slot again you can use: FAT_DebugFreeSlot(slotnumber), which removes the variable from the console display.
IMPORTANT 1: If you add variables make sure they are valid through while FAT_Render() will be called. Local variables are only valid if they are in the same function as the call to FAT_Render() or if they are used in a function which is "ABOVE" the one which calls FAT_Render(). Global variables works in any case.
IMPORTANT 2: If you add short or long variables make sure that these variables are REALLY of type short or long. If one of these variable isn't a short or long, it may be located on an odd address which may cause an address error.
IMPORTANT 3: Due to the fact that a string variable is already a pointer by itself (char*) it is a little bit tricky to use FAT_DBG_STRING types. Here is a simple example how to use them:
char* mystring = (char*)"abc"; // NOTE the additionally "&" sign!!! FAT_DebugUseSlot(0,"ABC string",&mystring,FAT_DBG_STRING);
To see a program which adds own variables to the CLIENTSLOT section, load Demo 9 and use it with FATLIB.DLL. It's not complicated to use the console with own variables and it comes in quite useful if you need to debug your program.
Under certain circumstances a program may want to open the console automatically to inform you that something happened. To open the console from a client program just call FAT_DebugConsole(FATCONFIG*) and hand-over a pointer to the active FATCONFIG. That's all. This way you can even debug local variables in any function like this:void MyFunc(FATCONFIG* fc) { short localvar; .... .... if (something_happened) { //-------------------------------------------------------------------- // use CLIENTSLOT 10 for local variable //-------------------------------------------------------------------- FAT_DebugUseSlot(10,"some_name",&localvar,FAT_DBG_SHORT_DEC); //-------------------------------------------------------------------- // open the console //-------------------------------------------------------------------- FAT_DebugConsole(fc); //-------------------------------------------------------------------- // remove the local variable again from slot 10 (because the pointer // to it becomes invalid when we return from MyFunc()) //-------------------------------------------------------------------- FAT_DebugFreeSlot(10); } }Easy, isn't it? IMHO this is the most useful debugging support I have seen yet within a calc program.
Just use FATLIB_C.DLL in combination with an "instrumented" program ...
Suppose you are using the VTI to run a program and you want to change the camera position on the map. By using the console version of the FAT-Engine (FATLIB_C.DLL) this becomes very easy. Here are the necessary steps:NOTE: If you change the memory directly like described above EVERYTHING can happen. So don't blame on the engine or on the program if you set (for example) a camera position which is out of the map or similar.
- start the program and hit the console hotkey ([4],[5] and [6] pressed simultaneously) to open the console
- Press [DOWN] until you see the FATCONFIG page. The first parameter (PTR) displayed on this page is the memory address where the active FATCONFIG "resides". The camera position is part of this structure.
- Hit F11 to enter the Debugger of the VTI. Click right on the memory window (down left), choose "go to address" and enter the address displayed on the FAT-Engine console for parameter PTR (you haven't to enter leading zeros).
- Well, now we are exactly there where the data of the FATCONFIG is stored. The next step is to evaluate where exactly cam_xpos and cam_ypos are located. Open headerfile fat.h and check the definition of structure FATCONFIG. We have to count the bytes in front of cam_xpos. There are 3 shorts (=6 bytes) and 3 pointers (=12 bytes) which sums up to 18 bytes. Go back to the memory view and skip there 18 bytes. Each row consists of 8 bytes. So we have to skip 2 rows and 2 bytes.
- Now we have found cam_xpos. Note that cam_xpos is a short therefore it takes up 2 bytes. Set the content of these bytes to whatever you want. Due to the fact that cam_ypos comes directly behind cam_xpos in the FATCONFIG structure the next 2 bytes are for cam_ypos. Change them, too.
- Close the debugger window by pressing F5.
- Press once [UP] and [DOWN] to refresh the displayed console page and you will see that cam[x] and cam[y] contain now your new values. If they won't change you have done something wrong.
It's very likely that you crash the program this way.