123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- /* $Id$
- * MegaZeux
- *
- * Copyright (C) 1996 Greg Janson
- * Copyright (C) 1998 Matthew D. Williams - dbwilli@scsn.net
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- /* TIMER.C- C code to fix timer for 500 ticks per second and run a
- delay function. This is C and not C++ so the interrupt
- functions prototype correctly. I tried to convert it to C++
- but C++ wants interrupt functions to be (...) and not
- (bp,di,etc) so it was too akward to be worth it. */
- #include "profile.h"
- #include "string.h"
- #include "sfx.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <dos.h>
- #include <time.h>
- #include "timer.h"
- #define TIMER_TICK 0x8
- #define RegList1 unsigned bp, unsigned di, unsigned si, unsigned ds
- #define RegList2 unsigned es, unsigned dx, unsigned cx, unsigned bx
- #define RegList3 unsigned ax, unsigned ip, unsigned cs, unsigned flags
- #define RegIntList RegList1,RegList2,RegList3
- int in_timer;/* Prevent reentrancy */
- char tick_count=0;/* Keeps track of clock ticks for INT 8 */
- char tick_target=27;/* The target number for tick_count */
- void interrupt (*oldint8)(void);/* Holds old INT 8 vector */
- void interrupt timer_system(RegIntList);
- char timer_installed=0;/* To remember if it is already installed */
- volatile int tcycle=0;
- /* Initializes the new vector. If called while already installed,
- simply realigns the timer speed. */
- void install_timer(void) {
- if(!timer_installed) {
- in_timer=0;
- oldint8=getvect(TIMER_TICK); /* get the original vector */
- }
- disable(); /* Ints off to set timer */
- outportb(0x043,0x034); /* Counter 0, read lsb-msb */
- /* mode 2, rate generator, */
- /* divide by N (0x0952h) */
- outportb(0x040,0x052); /* Low byte of 0x00952 */
- outportb(0x040,0x009); /* High byte of 0x00952 */
- /* Clock tick is now 500 */
- /* ticks per second... */
- /* (note- use 0x004A9 for */
- /* 1000 ticks...) */
- if(!timer_installed) {
- setvect(TIMER_TICK,timer_system);/* set up our ISR. */
- timer_installed=1;
- }
- enable(); /* ...and off we go... */
- }
- /* Uninstall the timer routine. */
- void uninstall_timer(void) {
- if(timer_installed) {
- timer_installed=0;
- disable(); /* Interrupts off */
- outportb(0x043,0x034); /* Counter 0, read lsb-msb */
- /* mode 2, rate generator, */
- /* divide by N */
- outportb(0x040,0x000); /* Low byte of 0x00000 */
- outportb(0x040,0x000); /* High byte of 0x00000 */
- /* Clock tick is now 18.2 */
- /* ticks/sec (normal rate) */
- setvect(TIMER_TICK,oldint8); /* Restore timer ISR */
- enable(); /* ...and off we go... */
- }
- }
- #pragma warn -par /* Turn off warnings that I know about here */
- #pragma warn -aus
- #pragma warn -use
- /* Calls original ISR 27 times, then 28 times, etc. (fluctuates to get an
- average of 27.5 times which results in a 18.18 timer rate) */
- void interrupt timer_system(RegIntList) {
- unsigned temp[3]; /* temporary storage area */
- outportb(0x020,0x020); /* Send EOI to 8259 PIC */
- if(!in_timer) { /* Prevent reentrancy */
- in_timer=1; /* Ok, we're in, lock the door... */
- tcycle++;
- if(tcycle<0) tcycle=32767;//Prevent overflow to negative (lockups!)
- #ifdef PROFILE
- if(curr_stack_pos>=0) {
- total_clicks++;
- func_clicks[func_stack[curr_stack_pos]]++;
- }
- #endif
- /* Do mouse countdown, sound code, disk code, etc. here */
- sound_system();
- in_timer=0;
- }
- if((++tick_count)>=tick_target) { /* Have we had 27 or 28 ticks? */
- tick_count=0; /* Yes, reset count to 0 */
- tick_target^=7; /* Target fluctuates between 27 and 28 */
- /* chain to clock ISR */
- temp[0] = bp; /* Save top 3 values */
- temp[1]=di;
- temp[2]=si;
- bp=ds; /* Move all others up by 3 */
- di=es;
- si=dx;
- ds=cx;
- es=bx;
- dx=ax;
- cx=FP_OFF(oldint8);/* and put a new ip/cs/flags */
- bx=FP_SEG(oldint8);/* on the stack */
- ax=flags&~0x200;
- _BP-=6; /* Modify BP by three words */
- return; /* NOTE: after changing _BP, don't */
- } /* plan on using any local variables, */
- /* other than those here. */
- }
- void far delay_time(int cycles) {
- tcycle=0;
- while(tcycle<cycles) ;
- }
- //Profiling code
- #ifdef PROFILE
- //Registered functions
- #define MAX_REG 50
- char reg_funcs[MAX_REG][30];
- char next_reg=0;
- //Time spent
- long func_clicks[MAX_REG];
- long total_clicks=0;
- //Function stack
- #define STACK_SIZE 50
- char func_stack[STACK_SIZE];
- char curr_stack_pos=-1;
- void PROFILING_INIT(void) {
- int t1;
- next_reg=1;
- total_clicks=0;
- for(t1=0;t1<MAX_REG;t1++) {
- func_clicks[t1]=0;
- reg_funcs[t1][0]=0;
- }
- str_cpy(reg_funcs[0],"Other");
- }
- #pragma startup PROFILING_INIT
- //Turn ON profiling
- void PROFILING_ON(void) {
- int t1;
- for(t1=0;t1<STACK_SIZE;t1++)
- func_stack[t1]=0;
- curr_stack_pos=0;
- }
- //Turn OFF profiling
- void PROFILING_OFF(void) {
- curr_stack_pos=-1;
- }
- //Register a function
- char REGISTER_FUNC(char far *name) {
- if(next_reg>=MAX_REG) return 0;
- str_cpy(reg_funcs[next_reg],name);
- return next_reg++;
- }
- //Select a function
- void SELECT_FUNC(char which) {
- if(curr_stack_pos>=STACK_SIZE) return;
- func_stack[++curr_stack_pos]=which;
- }
- //Stop a function
- void POP_FUNC(void) {
- if(curr_stack_pos<=0) return;
- func_stack[curr_stack_pos--]=0;
- }
- //Summarize stuff
- void PROFILING_SUMMARY(void) {
- int t1;
- curr_stack_pos=-1;
- for(t1=0;t1<18;t1++) {
- printf("Function %20s- %9.9ld ticks (%3.3d percent)\n",reg_funcs[t1],
- func_clicks[t1],func_clicks[t1]*100L/total_clicks);
- }
- //More?
- if(next_reg>18) {
- printf("[ Press any key for more... ]");
- if(!getch()) getch();
- printf("\n");
- for(t1=18;t1<36;t1++) {
- printf("Function %20s- %9.9ld ticks (%3.3d percent)\n",reg_funcs[t1],
- func_clicks[t1],func_clicks[t1]*100L/total_clicks);
- }
- //More?
- if(next_reg>36) {
- printf("[ Press any key for more... ]");
- if(!getch()) getch();
- printf("\n");
- for(t1=36;t1<MAX_REG;t1++) {
- printf("Function %20s- %9.9ld ticks (%3.3d percent)\n",reg_funcs[t1],
- func_clicks[t1],func_clicks[t1]*100L/total_clicks);
- }
- }
- }
- printf("\nTotal ticks- %9.9ld\n",total_clicks);
- printf("Save profiling report to PROFILE.TXT? ");
- t1=getch();
- if(!t1) t1=-getch();
- if((t1=='y')||(t1=='Y')) {
- FILE *fp=fopen("profile.txt","wt");
- for(t1=0;t1<MAX_REG;t1++) {
- fprintf(fp,"Function %20s- %9.9ld ticks (%3.3d percent)\n",reg_funcs[t1],
- func_clicks[t1],func_clicks[t1]*100L/total_clicks);
- }
- fprintf(fp,"\nTotal ticks- %9.9ld\n",total_clicks);
- fclose(fp);
- printf("\nReport written to PROFILE.TXT.");
- }
- }
- #endif
|