📄 flipants.c
字号:
/****************************************************************\
* *
* FLIPANTS - Control program for FLIPDRV. *
* *
* Makes extended KCT call to turn Flip mode on or off. *
* Takes its interrupt vector from IT.INI, if found. *
* *
* Copyright 1993, Paul Williamson, KB5MU. All rights reserved. *
* *
\****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#define DEFAULT_KCT_INT 0x63 /* Default KCT interrupt vector */
int main(int argc, char **argv);
int get_onoff(char *arg);
FILE *it_fopen(char *filename, char *mode);
int get_int_number(FILE *fp);
int flipdrv_present(int intno);
int yesorno(void);
void set_flipdrv(int onoff, int intno);
int get_flipdrv(int intno);
int main(int argc, char **argv)
{
FILE *fp; /* File pointer for reading IT.INI */
int intno; /* Interrupt vector number to use for KCT calls */
int onoff; /* Status to set FlipDRV to: 0 = normal mode
1 = inverted mode
-1 = don't set anything */
#define DONT_SET (-1)
printf("FlipAnts 0.6 - Copyright 1993 Paul Williamson, KB5MU\n");
if (argc > 2)
{
printf(" Usage: flipants [on|off]\n");
exit(1);
}
else if (argc == 2)
onoff = get_onoff(argv[1]); /* A value was specified; go get it */
else
onoff = DONT_SET; /* No value specified, so don't set one */
/* Starting with beta version 1.01b, InstantTrack uses a file called
IT.INI to contain various configuration parameters. If we're
using one, we can take the KCT interrupt number from there. */
if ((fp = it_fopen("IT.INI", "r")) != NULL)
{
intno = get_int_number(fp); /* Scan IT.INI for the KCT vector */
(void) fclose(fp);
}
else
intno = DEFAULT_KCT_INT; /* Default to standard KCT interrupt */
if (flipdrv_present(intno)) /* Check for FlipDRV before calling it */
{
if (onoff != DONT_SET)
set_flipdrv(onoff, intno); /* Set the specified mode */
/* Either way, report current status. */
printf("Flip mode is: %s.\n", get_flipdrv(intno) ? "inverted" : "normal");
}
return 0;
}
/*****************************************************\
* *
* get_onoff *
* *
* Take an "on" or "off" string and return its value. *
* If the string doesn't contain "on" or "off" (case *
* insensitive), issue a message and exit. *
* *
* Returns: 0 for "off" *
* 1 for "on" *
* *
\*****************************************************/
int get_onoff(char *arg)
{
if (stricmp(arg, "on") == 0)
return 1;
else if (stricmp(arg, "off") == 0)
return 0;
else
{
printf("\"%s\" is not valid. Use \"on\" or \"off\".\n", arg);
exit(1);
}
}
/*******************************************************\
* *
* it_fopen *
* *
* Try to open an InstantTrack auxiliary file. Look in *
* the directory given by the INSTANTTRACK environment *
* variable, if there is one. If that doesn't work, *
* look in the current directory. Otherwise, works *
* like fopen. *
* *
\*******************************************************/
FILE *it_fopen(char *filename, char *mode)
{
FILE *fp;
char buf[80]; /* Build a path in this buffer */
char *path; /* Path from the environment variable */
if ((path = getenv("INSTANTTRACK")) != NULL)
{
strncpy(buf, path, 40); /* Bogusly short, but this is what IT.EXE does */
strcat(buf, "\\"); /* Not idiotproof,but this is what IT.EXE does */
}
else
buf[0] = '\0'; /* Otherwise, start with empty path string */
strcat(buf,filename); /* build composite filespec */
if ((fp = fopen(buf, mode)) == NULL) /* Try with the INSTANTTRACK path */
fp = fopen(filename, mode); /* If that fails, try current path */
return fp; /* return the result, whatever it may be */
}
/**********************************************************\
* *
* get_int_number *
* *
* Look through a preopened file for a line of the form *
* kct_int_number = xxx *
* and return the value of xxx. If no such line is found, *
* return the default KCT interrupt value. *
* *
\**********************************************************/
#define BUFLEN 128 /* Big enough for most text lines */
int get_int_number(FILE *fp)
{
char buf[BUFLEN]; /* Line buffer for reading IT.INI */
int intno; /* The KCT interrupt number we're looking for */
while (fgets(buf, BUFLEN, fp) != NULL)
if (sscanf(buf, " kct_int_number = %x", &intno) == 1)
return intno;
return DEFAULT_KCT_INT;
}
/*************************************************************\
* *
* flipdrv_present *
* *
* Look at the chain of RotorDRV-like programs hooked into *
* the specified interrupt, and try to find FlipDRV among *
* them. This makes use of the KB5MU convention for chaining *
* RotorDRV programs. Each TSR stores the entry address of *
* the previous TSR at an address 4 bytes beyond its own *
* entry point. In addition, each TSR places the string *
* "RotorDRV" 10 bytes beyond its entry point, as defined by *
* the Kansas City Tracker specification. This is required *
* to allow application programs to identify the chain of *
* programs as a RotorDRV. My TSRs add a "+" and the name *
* of the TSR to the "RotorDRV" signature. This allows a *
* program to determine exactly what's in the chain. *
* *
* If a RotorDRV is found but FlipDRV is not found, ask *
* the user if he wants to continue anyway. This may be *
* required if one of the TSR programs in the stack *
* doesn't follow the above convention. *
* *
* Returns: 1 if FlipDRV is found, or if the user agrees *
* to continue anyway. *
* 0 otherwise. *
* *
\*************************************************************/
int flipdrv_present(int intno)
{
void far *entry_p; /* Pointer to function entry point */
char far *signature_p; /* Pointer to signature string */
int tsrs_found = 0; /* Count of RotorDRV TSRs found */
/* Start with the current ISR entry point */
entry_p = (void far *)_dos_getvect(intno);
for (;;) /* Loop through the chain of RotorDRV TSRs */
{
signature_p = ((char far *)entry_p) + 10; /* Point to the signature */
if ( _fmemcmp(signature_p, (void far *)"RotorDRV", 8) == 0)
{
tsrs_found++;
if (_fmemcmp(signature_p, (void far *)"RotorDRV+FlipDRV", 16) == 0)
return 1; /* Found FlipDRV */
else
entry_p = *(void far * far *)((char far *)entry_p + 4); /* Follow chain */
}
else if (tsrs_found == 0)
{
printf("No RotorDRV is installed. Can't FlipAnts without one!\n");
exit(1);
}
else
{
printf("I can't find FlipDRV. Shall I proceed anyway? (y/N) ");
fflush(stdout);
return yesorno();
}
}/* end of infinite loop */
}
/************************************************************\
* *
* yesorno *
* *
* Simpleminded function to get a Y or (anything else is no) *
* answer from the user. Use stdin to allow redirction for *
* automation. *
* *
\************************************************************/
int yesorno(void)
{
char buf[BUFLEN]; /* Buffer for the reply */
if (fgets(buf, BUFLEN, stdin) != NULL)
{
if (buf[0] == 'y' || buf[0] == 'Y')
return 1;
else
return 0;
}
}
/*********************************************************\
* *
* set_flipdrv *
* *
* Send the specified on/off value to the RotorDRV chain. *
* *
\*********************************************************/
void set_flipdrv(int onoff, int intno)
{
union REGS regs;
regs.h.ah = 0x7F; /* Command code */
regs.h.al = onoff; /* Argument */
int86(intno, ®s, ®s); /* Make the call */
}
/*******************************************************\
* *
* get_flipdrv *
* *
* Get the current on/off value from the RotorDRV chain *
* and return it. *
* *
\*******************************************************/
int get_flipdrv(int intno)
{
union REGS regs;
regs.h.ah = 0x7E; /* Command code */
int86(intno, ®s, ®s); /* Make the call */
return (int) regs.h.al; /* Return value from FlipAnts */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -