📄 joy.c
字号:
/*====================================================================*/
/* */
/* NOTE: Ensure this program is compiled for LARGE model. */
/* Non-ANSI stuff is pertinent to Microsoft QuickC v2.5. */
/* Porting to another compiler should not be too hard! */
/* */
/*====================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <string.h>
#include <memory.h>
#define FALSE 0
#define TRUE 1
#define FIRE_BUTTON1 0x01
#define FIRE_BUTTON2 0x02
#define BLACK 0 /* Std colour for black in default palette */
#define WHITE 15 /* Std colour for white in default palette */
typedef unsigned char BOOL;
typedef unsigned char BYTE;
/* NB: Most of the functions below are to aid in the demonstration of the */
/* joystick routines. They are quick and simple - no effort has been made */
/* to make them efficient. Feel free to modify them as you require! */
BYTE *pVideo=(BYTE *)0xA0000000L; /* Ptr to base of VGA video RAM */
void SetVideoMode( int nMode )
{
/* Simple routine to set the video mode using the BIOS video interrupt */
_asm mov ah, 00H
_asm mov al, byte ptr nMode
_asm int 10H
}
void SetPixel( int x, int y, int colour )
{
/* Very simple (inefficient) way of setting a pixel colour */
*(pVideo+(unsigned)y*320U+(unsigned)x) = (BYTE)colour;
}
void DrawCross( int cx, int cy, int colour )
{
/* Simple function to draw a 'cross-hair' cursor. */
#define XWTH 4 /* Aspect ration in 320x200 is approx 3/4 */
#define YHT 3
int x, y;
if ( cx>=0 && cx<320 )
{
for ( y=cy-YHT; y<=cy+YHT; y++ )
{
if ( y>=0 && y<200 ) SetPixel( cx,y,colour );
}
}
if ( cy>=0 && cy<200 )
{
for ( x=cx-XWTH; x<=cx+XWTH; x++ )
{
if ( x>=0 && x<320 ) SetPixel(x,cy,colour);
}
}
}
void SetCursorPos( int col, int row )
{
/* Even though we will be in graphics mode we can ask the video BIOS */
/* to set our cursor position for displaying text... */
_asm mov ah, 02H
_asm mov bh, 00H
_asm mov dl, byte ptr col
_asm mov dh, byte ptr row
_asm int 10H
}
/*===========================================================================
This text is taken from the RUTILS v2.0 manual:
These two functions allow an application to interrogate the
GAME port onto which up to two joysticks may be connected.
These two joysticks are numbered 1 and 2 and are serviced by
joystick_1() and joystick_2() respectively. Although these
functions return x and y count positions of the joystick the
values are NOT measured in screen or any other fixed units. In
fact, they are PC dependant timing values which will differ
from PC to PC. What this basically means is that an application
will need to CALIBRATE the joystick functions before any of the
results can be interpreted correctly. The calibration procedure
involves the determination of the minimum and maximum x and y
counts for joystick movement. This can really only be done by
asking the user to move the joystick to the top left and bottom
right respectively. In fact, some games ask the user to do this
and press the fire button to confirm the action. Once these
minimum and maximum values are known it is then a simple matter
of scaling the range to fit the required screen (pixel)
coordinates. The calibration procedure need only be performed
for one joystick.
Return Value:
An integer representing a bit mask comprising of FIRE_BUTTON_1
and/or FIRE_BUTTON_2. Each joystick has two fire buttons. If
neither button is pressed 0 is returned.
Example:
The following shows how to calibrate a joystick:
int min_x,min_y,max_x,max_y;
...
prints( "Move joystick to upper left & press FIRE\n\r",L_GREY,0 );
while ( !joystick_1(&min_x,&min_y) );
...
prints( "Move joystick to lower right & press FIRE\n\r",L_GREY,0 );
while ( !joystick_1(&max_x,&max_y) );
...
To scale a joystick "count" reading (j_x,j_y) to a pixel
position on a graphics screen the following equations can be
used:
pixel_x = (j_x - min_x) * (VS.mx+1) / (max_x - min_x);
pixel_y = (j_y - min_y) * (VS.my+1) / (max_y - min_y);
==============================================================================*/
int joystick_1( int *xc, int *yc )
{
/* Examine joystick 1 */
unsigned int i, count=0;
unsigned char state;
*xc=*yc=0;
_asm mov dx, 0201H
_asm mov al, 0FFH
_asm out dx, al
do
{
_asm mov dx, 0201H
_asm in al, dx
_asm mov state, al
if ( state&0x01 ) *xc=count;
if ( state&0x02 ) *yc=count;
count++;
}
while ( state&0x03 && count<65535U );
return( (int) ((state>>4)&0x03)^0x03 );
}
int joystick_2( int *xc, int *yc )
{
/* Examine joystick 2 */
unsigned int i, count=0;
unsigned char state;
*xc=*yc=0;
_asm mov dx, 0201H
_asm mov al, 0FFH
_asm out dx, al
do
{
_asm mov dx, 0201H
_asm in al, dx
_asm mov state, al
if ( state&0x04 ) *xc=count;
if ( state&0x08 ) *yc=count;
count++;
}
while ( state&0x0c && count<65535U );
return( (int) (state>>6)^0x03 );
}
/*========================= main program ====================================*/
void main( void )
{
int min_x, min_y, max_x, max_y, jx, jy, lastjx=-99, lastjy=-99;
printf( "\n\nJoystick Demo\n=============\n\nPress ESCape at any time to abort\n\n" );
/* Calibrate the joystick by finding its lowest and highest values */
printf( "Calibrating:\n\nMove joystick to top left and press a fire button" );
while ( !joystick_1(&min_x,&min_y) )
{
if ( kbhit() && getch()==27 ) exit( 1 );
}
/* Ensure button released before we do next one. On a fast machine the */
/* following loop will exit almost immediately 'cos the user hasn't */
/* lifted his finger off the button yet... */
while ( joystick_1(&jx,&jy) )
{
if ( kbhit() && getch()==27 ) exit( 1 );
}
printf( "\n\nMove joystick to bottom right and press a fire button" );
while ( !joystick_1(&max_x,&max_y) )
{
if ( kbhit() && getch()==27 ) exit( 1 );
}
/* Check for invalid range of values or idiot user(!) */
if ( min_x>=max_x || min_y>=max_y )
{
printf( "\n\nWooah! Wonky joystick dude!\n" );
exit( 1 );
}
/* Start the demo */
SetVideoMode( 0x13 ); /* Set the magic 320x200x256 linear graphics mode */
while ( 1 )
{
int buttons=joystick_1( &jx,&jy );
/* Check for exit */
if ( kbhit() && getch()==27 ) break;
/* Convert to pixel values */
if ( jx<min_x ) jx=min_x; /* Ensure within calibrated range */
if ( jx>max_x ) jx=max_x;
if ( jy<min_y ) jy=min_y;
if ( jy>max_y ) jy=max_y;
jx = (int)((long)(jx-min_x)*320L / (long)(max_x-min_x));
jy = (int)((long)(jy-min_y)*200L / (long)(max_y-min_y));
/* If changed from last position, update the cross hairs */
if ( lastjx!=jx || lastjy!=jy )
{
/* Erase the original if required */
if ( lastjx!=-99 ) DrawCross(lastjx,lastjy,BLACK);
/* Now draw the new position and record it for later */
DrawCross( lastjx=jx,lastjy=jy,WHITE );
}
/* Special POW! effect when a button pressed */
if ( buttons )
{
/* Convert pixel values to character positions. In 320x200, BIOS */
/* font is 8x8 pixels in size... */
int cx=jx/8-2, cy=jy/8, tx, ty;
/* Display POW! */
SetCursorPos( cx,cy );
printf( "%s",(buttons&FIRE_BUTTON1?"Pow1":"Pow2") );
/* Wait for the button to be released */
while ( joystick_1(&tx,&ty) );
/* Remove POW! message and redraw cross hairs */
SetCursorPos( cx,cy );
printf( " " );
DrawCross( lastjx,lastjy,WHITE );
}
}
/* Restore normal 80x25 text mode */
SetVideoMode( 0x03 );
printf( "Joystick Demo Coded by CyberFrog 8:)\n\n" );
printf( "Min Values: %u,%u\n",min_x,min_y );
printf( "Max Values: %u,%u\n",max_x,max_y );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -