_TAKING UP RESIDENCE WITH CODERUNNER_ by R. Bradley Andrews [LISTING ONE] #include "cr.h" /** RESIDENT CODE STACK SPACE **/ #define HK_STK 150 /* Stack size for Hot-Key services */ #define SR_STK 64 /* Stack for COM services */ #define STK_SZ (HK_STK+SR_STK) /* Size in words */ word isr_stk[STK_SZ+1]; /* Allow allways extra word ! */ extern popclock(); /* Main TSR entry, called by scheduler */ extern hk_isr(); /* Hot-Key service in HELLO.C */ extern word hk_list[]; /* This is in HELLOINI.C for use by isr() function */ /******** Disposable messages in MSICLDAT.C **************/ extern char sms[]; /* Signon screen */ extern char attrc[],attrm[]; /* Screen attributes used for signon */ extern char already[]; /* Message when already loaded */ extern char unloaddone[]; extern char unloadproblem[]; extern word init_data_end; /* Marker for end of disposable data */ /* Dummy function marks start of disposable code */ init_code_start() { } /* this main is called only once on program load, after that it is discarded */ main() { int i; char *a; if(second_load()) /* Check if TSR already loaded */ { i=str_pos('-',cmd_line); if (i && ((cmd_line[i]|0x20)=='r')) { if(remove_tsr()) /* Remove TSR from memory */ { dspf(unloaddone); /* Inform about unloading */ } else dspf(unloadproblem); /* Inform about unloading */ } else dspf(already); /* Otherwise show Help message */ mv_crs(); /* Reposition real cursor */ return(1); /* Exit with errorlevel 1 */ } /***** Display Signon Screen *****/ clr_scr(); a = color ? attrc:attrm; /* Select proper screen attributes */ crs_x=20; crs_y=7; /* Location to put signon box */ dspf(sms,a); /* Show the screen */ crs_x=0; crs_y=scr_len-2; /* Move to the bottom of screen */ mv_crs(); /* Place real cursor there */ crs_y=0; /* Top line used to display clock */ idata_end=&init_data_end; /* This enables init data disposal. */ icode_beg=init_code_start; /* This enables init code disposal. */ stay_resident(isr_stk,STK_SZ*2); /* Enable resident mode */ install_hk(hk_list,hk_isr,STK_SZ*2,0x7F); /* HOT-KEY Support */ install_tsc(popclock,2*STK_SZ,1); /* Install tiny scheduler */ /* add_tsc_event(8L); /* Add event to timer, 8 ticks from now */ /* Popclock will be called by scheduler */ return(0); /* Set errorlevel to 0 */ } [LISTING TWO] /* this module contains ALL disposable data only. The marker at the end called init_end_data is just a marker to the end of disposable data NO CODE CAN BE PUT INTO THIS MODULE, DATA ONLY */ #include "cr.h" /* Video attributes for signon screen. The last one is for the Clock */ /*char attrc[]={0x17,0x1E,0x13,0x1F,0x1B,0x17}; /* Color screen attributes */ /*char attrm[]={0x07,0x0F,0x07,0x07,0x07,0x70}; /* Mono screen attributes */ /* This is the signon message */ char sms[]= "`0" "[_________________________[`m" "[`1 Timer 1.00 `0[`m" "[`2 DDDDDDDDDDD `0[`m" "[`4 Author: `0[`m" "[`4 R. Bradley Andrews `0[`m" "[\\\\\\\\\\\\\\\\\\\\\\\\\[`n`5"; char already[]="`nError - Timer already present." "`nEnter MSICLOCK -R to unload.`n"; word hk_list[]={M_RS+0x44,0}; /* Right-Shift Enter */ char unloaddone[]="Timer has been removed from memory.`n"; char unloadproblem[]="Timer could not be removed from memory."; char _tsr_name[]="Timer"; struct cfg_rec config_block = { /* This record stays in only one module */ sizeof(config_block), /* Configuration block size */ 'T','I','M','E', /* Program ID string */ 100, /* Version 1.00 */ }; /**** STORE THIS IMMEDIATELY AFTER THE LAST DISPOSABLE DATA ITEM ****/ /**** 1. Store all install_?? type function pointers into install_list ****/ fp install_list[]={install_tsc, install_hk, install_bk}; /* Only tiny scheduler used */ /**** 2. Put Marker for the end-of-init-data (must be = NONZERO) ****/ word init_data_end=1; /************************************************************************/ [LISTING THREE] #include "cr.h" /** RESIDENT CODE STACK SPACE **/ #define HK_STK 150 /* Stack size for Hot-Key services */ #define SR_STK 100 /* Stack for COM services */ #define STK_SZ (HK_STK+SR_STK) /* Size in words */ #define kWidth 13 /* width of display string */ char time_str[]=" 00:00:00:00 "; char blank_str[]=" "; word sbuf[kWidth]; char attrc[]={0x17,0x1E,0x13,0x1F,0x1B,0x17}; /* Color screen attributes */ char attrm[]={0x07,0x0F,0x07,0x07,0x07,0x70}; /* Mono screen attributes */ long start_ticks; int which=0; popclock(void) { register char *t,*s; register long cur_ticks; struct time_rec cur_time; if (which==1) { add_tsc_event(1L); /* Setup next event in 1/3 second */ } cur_ticks = bios_ticks(); cur_ticks = cur_ticks - start_ticks; ticks2time(cur_ticks, &cur_time); t=&cur_time.hours; /* Prepare to convert hh:mm:ss */ s=time_str+1; do cv_b2dec((byte)*t,s), s+=3; /* Convert 1 byte to decimal */ while (--t>=&cur_time.sec100); /* Until done with seconds */ chk_video(); /* Obtain current video settings */ crs_x=scr_width-kWidth; /* Set cursor to upper right corner */ dsp(time_str); /* Display time string there */ } hk_isr() { if (!which) { crs_x=scr_width-kWidth; /* Set cursor to upper right corner */ get_block(kWidth,1,sbuf); start_ticks = bios_ticks(); add_tsc_event(1L); /* Add event to timer, 8 ticks from now */ which++; } else { if (which == 1 ) { which++; } else { crs_x=scr_width-kWidth; /* Set cursor to upper right corner */ put_block(kWidth,1,sbuf); which = 0; } } } [LISTING FOUR] REM Use switch d for debug mode REM if %1x==dx goto compdebug tcc -c -I..\ -DPDK1 timer*.c goto linkit rem :compdebug tcc -c -v -I..\ -DDBG timer*.c :linkit del timerini.lib lib timerini +timerini; if %1x==dx goto dbg :lnk1 link ..\r0 timerdat timer ..\r1,timer,,..\k1 ..\cr timerini/NOI/NOD/M; goto exit :dbg tlink ..\r0 timerdat timer ..\r1,timer,,..\cr timerini/c/m/v; :exit