/****************************************************************************** * * project name: TICT Tutorial Series 1 - PART III * file name: tsrclock.c * initial date: 02/11/2000 * author: thomas.nussbaumer@gmx.net * * description: bootstrap loader/terminator for a TSR program * * ----------------------------------------------------------------------------- * steps of the program * ----------------------------------------------------------------------------- * * (1) function HeapEnd is used to retrieve the actual end of the heap * (2) search the heap for the signature of the given program * (3) if we've found the program call its _main() again and free memory afterwards * (4) else: * (a) allocate memory at the high end of the heap * (b) copy signature to this memory * (c) copy program to this memory * (d) relocate it * (e) call _main() of program * (f) return WITHOUT freeing the memory * * ----------------------------------------------------------------------------- * conventions for a TSR program * ----------------------------------------------------------------------------- * * (1) be aware that _main() is called twice. the first call should perform the * initialization of your program and the second call should perform a * final cleanup (program will be removed afterwards). * * * * build this program by typing: tigcc -O2 tsrclock.c * * * $Id: tsrclock.c,v 1.2 2001/02/10 18:59:22 Thomas Nussbaumer Exp $ * ******************************************************************************/ #include #define MAGIC_TSR 0x54535231 // magic marker for TSR program ("TSR1") int _ti89, _ti92plus; // produce code for TI89 and TI92plus //--------------------------------------------------------- // the size of the TSR program is stored in the first // two bytes of the hexcode array (this holds true for all // TI variables) //--------------------------------------------------------- #define SIZE_OF_PRG (sample_prg[0] * 256 + sample_prg[1] + 2) //---------------------------------------------------------- // sample TSR program (see sample.c for its source code) // // compiled with: tigcc -O2 -outputbin sample.c // and converted to an array with the ttbin2hex tool //---------------------------------------------------------- unsigned char sample_prg[] = { 0x02,0x3d,0x08,0xd7,0x00,0x07,0x4e,0xf9,0x00,0x00, 0x01,0x48,0x25,0x30,0x32,0x64,0x3a,0x25,0x30,0x32, 0x64,0x3a,0x25,0x30,0x32,0x64,0x00,0x00,0x4e,0x56, 0xff,0x9c,0x2f,0x0a,0x2f,0x03,0x34,0x7c,0x00,0xc8, 0x20,0x52,0x3f,0x39,0x00,0x00,0x01,0x86,0x3f,0x39, 0x00,0x00,0x01,0x88,0x3f,0x39,0x00,0x00,0x01,0x8a, 0x48,0x7a,0xff,0xce,0x76,0x9c,0xd6,0x8e,0x2f,0x03, 0x20,0x68,0x01,0x4c,0x4e,0x90,0x20,0x52,0x2f,0x03, 0x20,0x68,0x03,0x98,0x4e,0x90,0x26,0x2e,0xff,0x94, 0x24,0x6e,0xff,0x98,0x4e,0x5e,0x4e,0x75,0x4e,0x56, 0x00,0x00,0x30,0x39,0x00,0x00,0x01,0x8c,0x67,0x3c, 0x33,0xfc,0x00,0x00,0x00,0x00,0x01,0x8c,0x30,0x39, 0x00,0x00,0x01,0x8c,0x33,0xc0,0x00,0x00,0x01,0x8a, 0x30,0x39,0x00,0x00,0x01,0x8a,0x33,0xc0,0x00,0x00, 0x01,0x88,0x30,0x39,0x00,0x00,0x01,0x88,0x33,0xc0, 0x00,0x00,0x01,0x86,0x30,0x39,0x00,0x00,0x01,0x86, 0x33,0xc0,0x00,0x00,0x01,0x84,0x60,0x00,0x00,0x8e, 0x30,0x39,0x00,0x00,0x01,0x84,0x52,0x40,0x33,0xc0, 0x00,0x00,0x01,0x84,0x30,0x39,0x00,0x00,0x01,0x84, 0x0c,0x40,0x00,0x13,0x66,0x72,0x33,0xfc,0x00,0x00, 0x00,0x00,0x01,0x84,0x30,0x39,0x00,0x00,0x01,0x86, 0x52,0x40,0x33,0xc0,0x00,0x00,0x01,0x86,0x4e,0xba, 0xff,0x40,0x30,0x39,0x00,0x00,0x01,0x86,0x0c,0x40, 0x00,0x3c,0x66,0x4c,0x33,0xfc,0x00,0x00,0x00,0x00, 0x01,0x86,0x30,0x39,0x00,0x00,0x01,0x88,0x52,0x40, 0x33,0xc0,0x00,0x00,0x01,0x88,0x30,0x39,0x00,0x00, 0x01,0x88,0x0c,0x40,0x00,0x3c,0x66,0x2a,0x33,0xfc, 0x00,0x00,0x00,0x00,0x01,0x88,0x30,0x39,0x00,0x00, 0x01,0x8a,0x52,0x40,0x33,0xc0,0x00,0x00,0x01,0x8a, 0x30,0x39,0x00,0x00,0x01,0x8a,0x0c,0x40,0x00,0x18, 0x66,0x08,0x33,0xfc,0x00,0x00,0x00,0x00,0x01,0x8a, 0x20,0x79,0x00,0x00,0x01,0x80,0x48,0x79,0x00,0x00, 0x01,0x44,0x40,0xe7,0x4e,0xd0,0x4e,0x5e,0x4e,0x75, 0x4e,0x56,0x00,0x00,0x20,0x39,0x00,0x00,0x01,0x80, 0x67,0x0e,0x23,0xc0,0x00,0x04,0x00,0x74,0x42,0xb9, 0x00,0x00,0x01,0x80,0x60,0x1a,0x33,0xfc,0x00,0x01, 0x00,0x00,0x01,0x8c,0x23,0xf8,0x00,0x74,0x00,0x00, 0x01,0x80,0x23,0xfc,0x00,0x00,0x01,0x8e,0x00,0x04, 0x00,0x74,0x4e,0x5e,0x4e,0x75,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0x46,0xfc,0x27,0x00,0x48,0xe7,0xff,0xfe,0x4e,0xb9, 0x00,0x00,0x00,0x60,0x4c,0xdf,0x7f,0xff,0x4e,0x73, 0x00,0x00,0x01,0x48,0x00,0x06,0x01,0x86,0x00,0x2a, 0x01,0x88,0x00,0x30,0x01,0x8a,0x00,0x36,0x01,0x8c, 0x00,0x66,0x01,0x8c,0x00,0x70,0x01,0x8c,0x00,0x76, 0x01,0x8a,0x00,0x7c,0x01,0x8a,0x00,0x82,0x01,0x88, 0x00,0x88,0x01,0x88,0x00,0x8e,0x01,0x86,0x00,0x94, 0x01,0x86,0x00,0x9a,0x01,0x84,0x00,0xa0,0x01,0x84, 0x00,0xaa,0x01,0x84,0x00,0xb2,0x01,0x84,0x00,0xb8, 0x01,0x84,0x00,0xc6,0x01,0x86,0x00,0xcc,0x01,0x86, 0x00,0xd4,0x01,0x86,0x00,0xde,0x01,0x86,0x00,0xec, 0x01,0x88,0x00,0xf2,0x01,0x88,0x00,0xfa,0x01,0x88, 0x01,0x00,0x01,0x88,0x01,0x0e,0x01,0x8a,0x01,0x14, 0x01,0x8a,0x01,0x1c,0x01,0x8a,0x01,0x22,0x01,0x8a, 0x01,0x30,0x01,0x80,0x01,0x36,0x01,0x44,0x01,0x3c, 0x01,0x80,0x01,0x4e,0x01,0x80,0x01,0x5c,0x01,0x8c, 0x01,0x66,0x01,0x80,0x01,0x6e,0x01,0x8e,0x01,0x74, 0x00,0x60,0x01,0x98,0xf3}; //============================================================================= // installs TSR program // // returns 1 if successfully installed //============================================================================= int InstallTSR(unsigned char* signature) { unsigned char* mem = HeapAllocPtr(SIZE_OF_PRG+12); // +12 for signature //--------------------------------------------------- // in case of a "cannot allocate enough memory" error // we will immediately return //--------------------------------------------------- if (!mem) return 0; //----------------------------------------------------- // write MAGIC_TSR (4 bytes) at the beginning of memory //----------------------------------------------------- *mem++ = (MAGIC_TSR >> 24) & 0xff; *mem++ = (MAGIC_TSR >> 16) & 0xff; *mem++ = (MAGIC_TSR >> 8) & 0xff; *mem++ = (MAGIC_TSR ) & 0xff; //----------------------------------------------------- // copy afterwards the 8 bytes signature to memory //----------------------------------------------------- memcpy(mem,signature,8); mem+=8; //----------------------------------------------------- // ... and the program itself from the sample_prg array //----------------------------------------------------- memcpy(mem,sample_prg,SIZE_OF_PRG); //-------------------------------------------------------- // relocate program, bypass some protections introduced in // AMS 2.xx and execute _main routine of TSR //-------------------------------------------------------- EX_patch(mem + 0x40002, mem + SIZE_OF_PRG - 2 + 3 - 2); enter_ghost_space(); ASM_call(mem + 0x40002); return 1; } //============================================================================= // removes TSR program //============================================================================= void RemoveTSR(unsigned char* tsr_address) { //------------------------------------------------ // bypass some protections introduced in // AMS 2.xx and execute _main routine of TSR again //------------------------------------------------ enter_ghost_space(); ASM_call(tsr_address + 12 + 0x40002); //-------------------------------------------------- // fill memory holding signature with zeros and free // the buffer allocated by InstallTSR() //-------------------------------------------------- memset(tsr_address,0,12); HeapFreePtr(tsr_address); } //============================================================================= // try to find TSR on high heap // // an installed TSR starts with MAGIC_TSR (4 bytes) followed by an 8 byte // program signature // // the complete memory is scanned backwards starting at the address returned // by HeapEnd() until we'll reach address 0 (or we'll find the marker) // // returns address of already installed TSR or NULL //============================================================================= unsigned char* FindTSR(unsigned char* signature) { unsigned char* end = HeapEnd(); while (end) { if (*end == ((MAGIC_TSR >> 24) & 0xff) && *(end+1) == ((MAGIC_TSR >> 16) & 0xff) && *(end+2) == ((MAGIC_TSR >> 8) & 0xff) && *(end+3) == ((MAGIC_TSR ) & 0xff) && !strncmp(end+4,signature,8)) { // we have found the TSR .... return end; } end-=2; } //----------------------------------------------------- // if we'll come here we haven't found an installed TSR //----------------------------------------------------- return NULL; } //============================================================================= // as usual: a main entry point ... //============================================================================= void _main(void) { unsigned char signature[8] = {'t','s','r','c','l','o','c','k'}; unsigned char* tsr_address; //---------------------------------------------------- // try to find an already installed version of the TSR //---------------------------------------------------- tsr_address = FindTSR(signature); //------------------------------------------- // if we have found the signature on the heap // the TSR is already installed -> remove it //------------------------------------------- if (tsr_address) { RemoveTSR(tsr_address); ST_showHelp("TSR clock removed"); } //------------------------------------------- // otherwise try to install it ... else { if (!InstallTSR(signature)) { ST_showHelp("cannot install TSR clock"); } else { ST_showHelp("TSR clock installed"); } } } //============================================================================= // Revision History //============================================================================= // // $Log: tsrclock.c,v $ // Revision 1.2 2001/02/10 18:59:22 Thomas Nussbaumer // RemoveTSR: replaced faulty memset() call with correct one // (Thanx to Beat Oehrli [beat.oehrli@gbsvisp.ch] for reporting) // // Revision 1.1 2000/11/04 19:23:38 Thomas Nussbaumer // initial version // // //