timer.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /* $Id$
  2. * MegaZeux
  3. *
  4. * Copyright (C) 1996 Greg Janson
  5. * Copyright (C) 1998 Matthew D. Williams - dbwilli@scsn.net
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. /* TIMER.C- C code to fix timer for 500 ticks per second and run a
  22. delay function. This is C and not C++ so the interrupt
  23. functions prototype correctly. I tried to convert it to C++
  24. but C++ wants interrupt functions to be (...) and not
  25. (bp,di,etc) so it was too akward to be worth it. */
  26. #include "profile.h"
  27. #include "string.h"
  28. #include "sfx.h"
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <dos.h>
  32. #include <time.h>
  33. #include "timer.h"
  34. #define TIMER_TICK 0x8
  35. #define RegList1 unsigned bp, unsigned di, unsigned si, unsigned ds
  36. #define RegList2 unsigned es, unsigned dx, unsigned cx, unsigned bx
  37. #define RegList3 unsigned ax, unsigned ip, unsigned cs, unsigned flags
  38. #define RegIntList RegList1,RegList2,RegList3
  39. int in_timer;/* Prevent reentrancy */
  40. char tick_count=0;/* Keeps track of clock ticks for INT 8 */
  41. char tick_target=27;/* The target number for tick_count */
  42. void interrupt (*oldint8)(void);/* Holds old INT 8 vector */
  43. void interrupt timer_system(RegIntList);
  44. char timer_installed=0;/* To remember if it is already installed */
  45. volatile int tcycle=0;
  46. /* Initializes the new vector. If called while already installed,
  47. simply realigns the timer speed. */
  48. void install_timer(void) {
  49. if(!timer_installed) {
  50. in_timer=0;
  51. oldint8=getvect(TIMER_TICK); /* get the original vector */
  52. }
  53. disable(); /* Ints off to set timer */
  54. outportb(0x043,0x034); /* Counter 0, read lsb-msb */
  55. /* mode 2, rate generator, */
  56. /* divide by N (0x0952h) */
  57. outportb(0x040,0x052); /* Low byte of 0x00952 */
  58. outportb(0x040,0x009); /* High byte of 0x00952 */
  59. /* Clock tick is now 500 */
  60. /* ticks per second... */
  61. /* (note- use 0x004A9 for */
  62. /* 1000 ticks...) */
  63. if(!timer_installed) {
  64. setvect(TIMER_TICK,timer_system);/* set up our ISR. */
  65. timer_installed=1;
  66. }
  67. enable(); /* ...and off we go... */
  68. }
  69. /* Uninstall the timer routine. */
  70. void uninstall_timer(void) {
  71. if(timer_installed) {
  72. timer_installed=0;
  73. disable(); /* Interrupts off */
  74. outportb(0x043,0x034); /* Counter 0, read lsb-msb */
  75. /* mode 2, rate generator, */
  76. /* divide by N */
  77. outportb(0x040,0x000); /* Low byte of 0x00000 */
  78. outportb(0x040,0x000); /* High byte of 0x00000 */
  79. /* Clock tick is now 18.2 */
  80. /* ticks/sec (normal rate) */
  81. setvect(TIMER_TICK,oldint8); /* Restore timer ISR */
  82. enable(); /* ...and off we go... */
  83. }
  84. }
  85. #pragma warn -par /* Turn off warnings that I know about here */
  86. #pragma warn -aus
  87. #pragma warn -use
  88. /* Calls original ISR 27 times, then 28 times, etc. (fluctuates to get an
  89. average of 27.5 times which results in a 18.18 timer rate) */
  90. void interrupt timer_system(RegIntList) {
  91. unsigned temp[3]; /* temporary storage area */
  92. outportb(0x020,0x020); /* Send EOI to 8259 PIC */
  93. if(!in_timer) { /* Prevent reentrancy */
  94. in_timer=1; /* Ok, we're in, lock the door... */
  95. tcycle++;
  96. if(tcycle<0) tcycle=32767;//Prevent overflow to negative (lockups!)
  97. #ifdef PROFILE
  98. if(curr_stack_pos>=0) {
  99. total_clicks++;
  100. func_clicks[func_stack[curr_stack_pos]]++;
  101. }
  102. #endif
  103. /* Do mouse countdown, sound code, disk code, etc. here */
  104. sound_system();
  105. in_timer=0;
  106. }
  107. if((++tick_count)>=tick_target) { /* Have we had 27 or 28 ticks? */
  108. tick_count=0; /* Yes, reset count to 0 */
  109. tick_target^=7; /* Target fluctuates between 27 and 28 */
  110. /* chain to clock ISR */
  111. temp[0] = bp; /* Save top 3 values */
  112. temp[1]=di;
  113. temp[2]=si;
  114. bp=ds; /* Move all others up by 3 */
  115. di=es;
  116. si=dx;
  117. ds=cx;
  118. es=bx;
  119. dx=ax;
  120. cx=FP_OFF(oldint8);/* and put a new ip/cs/flags */
  121. bx=FP_SEG(oldint8);/* on the stack */
  122. ax=flags&~0x200;
  123. _BP-=6; /* Modify BP by three words */
  124. return; /* NOTE: after changing _BP, don't */
  125. } /* plan on using any local variables, */
  126. /* other than those here. */
  127. }
  128. void far delay_time(int cycles) {
  129. tcycle=0;
  130. while(tcycle<cycles) ;
  131. }
  132. //Profiling code
  133. #ifdef PROFILE
  134. //Registered functions
  135. #define MAX_REG 50
  136. char reg_funcs[MAX_REG][30];
  137. char next_reg=0;
  138. //Time spent
  139. long func_clicks[MAX_REG];
  140. long total_clicks=0;
  141. //Function stack
  142. #define STACK_SIZE 50
  143. char func_stack[STACK_SIZE];
  144. char curr_stack_pos=-1;
  145. void PROFILING_INIT(void) {
  146. int t1;
  147. next_reg=1;
  148. total_clicks=0;
  149. for(t1=0;t1<MAX_REG;t1++) {
  150. func_clicks[t1]=0;
  151. reg_funcs[t1][0]=0;
  152. }
  153. str_cpy(reg_funcs[0],"Other");
  154. }
  155. #pragma startup PROFILING_INIT
  156. //Turn ON profiling
  157. void PROFILING_ON(void) {
  158. int t1;
  159. for(t1=0;t1<STACK_SIZE;t1++)
  160. func_stack[t1]=0;
  161. curr_stack_pos=0;
  162. }
  163. //Turn OFF profiling
  164. void PROFILING_OFF(void) {
  165. curr_stack_pos=-1;
  166. }
  167. //Register a function
  168. char REGISTER_FUNC(char far *name) {
  169. if(next_reg>=MAX_REG) return 0;
  170. str_cpy(reg_funcs[next_reg],name);
  171. return next_reg++;
  172. }
  173. //Select a function
  174. void SELECT_FUNC(char which) {
  175. if(curr_stack_pos>=STACK_SIZE) return;
  176. func_stack[++curr_stack_pos]=which;
  177. }
  178. //Stop a function
  179. void POP_FUNC(void) {
  180. if(curr_stack_pos<=0) return;
  181. func_stack[curr_stack_pos--]=0;
  182. }
  183. //Summarize stuff
  184. void PROFILING_SUMMARY(void) {
  185. int t1;
  186. curr_stack_pos=-1;
  187. for(t1=0;t1<18;t1++) {
  188. printf("Function %20s- %9.9ld ticks (%3.3d percent)\n",reg_funcs[t1],
  189. func_clicks[t1],func_clicks[t1]*100L/total_clicks);
  190. }
  191. //More?
  192. if(next_reg>18) {
  193. printf("[ Press any key for more... ]");
  194. if(!getch()) getch();
  195. printf("\n");
  196. for(t1=18;t1<36;t1++) {
  197. printf("Function %20s- %9.9ld ticks (%3.3d percent)\n",reg_funcs[t1],
  198. func_clicks[t1],func_clicks[t1]*100L/total_clicks);
  199. }
  200. //More?
  201. if(next_reg>36) {
  202. printf("[ Press any key for more... ]");
  203. if(!getch()) getch();
  204. printf("\n");
  205. for(t1=36;t1<MAX_REG;t1++) {
  206. printf("Function %20s- %9.9ld ticks (%3.3d percent)\n",reg_funcs[t1],
  207. func_clicks[t1],func_clicks[t1]*100L/total_clicks);
  208. }
  209. }
  210. }
  211. printf("\nTotal ticks- %9.9ld\n",total_clicks);
  212. printf("Save profiling report to PROFILE.TXT? ");
  213. t1=getch();
  214. if(!t1) t1=-getch();
  215. if((t1=='y')||(t1=='Y')) {
  216. FILE *fp=fopen("profile.txt","wt");
  217. for(t1=0;t1<MAX_REG;t1++) {
  218. fprintf(fp,"Function %20s- %9.9ld ticks (%3.3d percent)\n",reg_funcs[t1],
  219. func_clicks[t1],func_clicks[t1]*100L/total_clicks);
  220. }
  221. fprintf(fp,"\nTotal ticks- %9.9ld\n",total_clicks);
  222. fclose(fp);
  223. printf("\nReport written to PROFILE.TXT.");
  224. }
  225. }
  226. #endif