📄 i_system.c
字号:
byte* I_AllocLow(int length)
{
byte* mem;
mem = (byte *)malloc (length);
memset (mem,0,length);
return mem;
}
#define MOUSE2
/* Secondary Mouse*/
#ifdef MOUSE2
_go32_dpmi_seginfo oldmouseinfo,newmouseinfo;
boolean mouse2_started=0;
USHORT mouse2port;
byte mouse2irq;
volatile int handlermouse2buttons;
volatile int handlermouse2x,handlermouse2y;
// internal use
volatile int bytenum;
volatile byte combytes[8];
//
// support a secondary mouse without mouse driver !
//
// take from the PC-GPE by Mark Feldman
static void I_MicrosoftMouseIntHandler()
{
char dx,dy;
byte inbyte;
// Get the port byte
inbyte = inportb(mouse2port);
// Make sure we are properly "synched"
if((inbyte & 64)== 64 || bytenum>7)
bytenum = 0;
// Store the byte and adjust bytenum
combytes[bytenum] = inbyte;
bytenum++;
// Have we received all 3 bytes?
if(bytenum==3)
{
// Yes, so process them
dx = ((combytes[0] & 3) << 6) + combytes[1];
dy = ((combytes[0] & 12) << 4) + combytes[2];
handlermouse2x+= dx;
handlermouse2y+= dy;
handlermouse2buttons = (combytes[0] & (32+16)) >>4;
}
else
if(bytenum==4) // for logitech 3 buttons
{
if(combytes[3] & 32)
handlermouse2buttons |= 4;
else
handlermouse2buttons &= ~4;
}
// Acknowledge the interrupt
outportb(0x20,0x20);
}
END_OF_FUNCTION(I_MicrosoftMouseIntHandler);
// wait ms milliseconde
void I_Delay(int ms)
{
tic_t starttime;
if(timer_started)
{
starttime=I_GetTime()+(TICRATE*ms)/1000;
while(starttime>=I_GetTime())
;
}
else
delay(ms);
}
//
// Removes the mouse2 handler.
//
void I_ShutdownMouse2()
{
event_t event;
int i;
if( !mouse2_started )
return;
outportb(mouse2port+4,0x00); // shutdown mouse (DTR & RTS = 0)
I_Delay(1);
outportb(mouse2port+1,0x00); // disable COM interuption
asm("cli");
_go32_dpmi_set_protected_mode_interrupt_vector(mouse2irq, &oldmouseinfo);
_go32_dpmi_free_iret_wrapper(&newmouseinfo);
asm("sti");
handlermouse2x=handlermouse2y=handlermouse2buttons=0;
// emulate the up of all mouse buttons
for(i=0;i<MOUSEBUTTONS;i++)
{
event.type=ev_keyup;
event.data1=KEY_2MOUSE1+i;
D_PostEvent(&event);
}
mouse2_started=false;
}
byte ComIrq[4]={0x0c,0x0b,0x0c,0x0b};
USHORT ComPort[4]={0x3F8,0x2F8,0x3E8,0x2E8};
//
// Installs the mouse2 handler.
//
void I_StartupMouse2()
{
int i;
boolean found;
__dpmi_regs r;
if( mouse2_started )
I_ShutdownMouse2();
if(!cv_usemouse2.value)
return;
handlermouse2x=handlermouse2y=handlermouse2buttons=0;
mouse2irq =ComIrq[cv_mouse2port.value-1];
mouse2port=ComPort[cv_mouse2port.value-1];
CONS_Printf("Using %s (irq %d, port 0x%x)\n",cv_mouse2port.string,mouse2irq-8,mouse2port);
r.x.ax=0x24;
__dpmi_int(0x33,&r);
if(r.h.cl+8==mouse2irq)
{
CONS_Printf("Irq conflict with mouse 1\n"
"Use mouse2port to change the port\n");
return;
}
// install irq wrapper
asm("cli");
_go32_dpmi_get_protected_mode_interrupt_vector(mouse2irq, &oldmouseinfo);
newmouseinfo.pm_selector=_go32_my_cs();
newmouseinfo.pm_offset=(int)I_MicrosoftMouseIntHandler;
_go32_dpmi_allocate_iret_wrapper(&newmouseinfo);
_go32_dpmi_set_protected_mode_interrupt_vector(mouse2irq, &newmouseinfo);
LOCK_VARIABLE(bytenum);
LOCK_VARIABLE(handlermouse2x);
LOCK_VARIABLE(handlermouse2y);
LOCK_VARIABLE(handlermouse2buttons);
LOCK_VARIABLE(mouse2port);
_go32_dpmi_lock_data(combytes,sizeof(combytes));
LOCK_FUNCTION(I_MicrosoftMouseIntHandler);
asm("sti");
outportb(mouse2port+4,0 ); // shutdown mouse (DTR & RTS = 0)
I_Delay(1);
outportb(mouse2port+1,0 ); // disable COM interuption
I_Delay(1);
outportb(mouse2port+3,0x80); // change status of port +0 et +1
I_Delay(1); // for baudrate programmation
outportb(mouse2port ,0x60); // 1200 LSB
I_Delay(1);
outportb(mouse2port+1,0 ); // 1200 MSB
I_Delay(1);
outportb(mouse2port+3,0x02); // set port protocol 7N1
I_Delay(1);
outportb(mouse2port+1,0x01); // enable COM interuption
I_Delay(1);
outportb(0x21,0x0);
// wait to be sure the mouse have shutdown
I_Delay(100);
outportb(mouse2port+4,0x0b); // restart mouse
i=I_GetTime()+TICRATE;
found=cv_usemouse2.value==2;
while (I_GetTime()<i || !found)
if(combytes[0]!='M')
found=true;
if(found || cv_usemouse2.value==2)
{
CONS_Printf("Microsoft compatible Secondary Mouse detected\n");
//register shutdown mouse2 code.
I_AddExitFunc(I_ShutdownMouse2);
mouse2_started = true;
}
else
{
CONS_Printf("Secondary Mouse not found\n");
// remove irq wraper
I_ShutdownMouse2();
}
}
#endif
// Initialise the mouse. Doesnt need to be shutdown.
//
void I_StartupMouse (void)
{
__dpmi_regs r;
// mouse detection may be skipped by setting usemouse false
if(cv_usemouse.value == 0)
{
mouse_detected=false;
I_ShutdownMouse2();
return;
}
//detect mouse presence
r.x.ax=0;
__dpmi_int(0x33,&r);
//added:03-01-98:
if( r.x.ax == 0 && cv_usemouse.value != 2)
{
mouse_detected=false;
CONS_Printf("\2I_StartupMouse: mouse not present.\n");
}
else
{
mouse_detected=true;
//hide cursor
r.x.ax=2;
__dpmi_int(0x33,&r);
//reset mickey count
r.x.ax=0x0b;
__dpmi_int(0x33,&r);
}
}
void I_GetEvent (void)
{
__dpmi_regs r;
event_t event;
int i;
#ifdef MOUSE2
// mouse may be disabled during the game by setting usemouse false
if (mouse2_started)
{
//mouse movement
static byte lastbuttons2=0;
// post key event for buttons
if (handlermouse2buttons!=lastbuttons2)
{
int j=1,k;
k=(handlermouse2buttons ^ lastbuttons2); // only changed bit to 1
lastbuttons2=handlermouse2buttons;
for(i=0;i<MOUSEBUTTONS;i++,j<<=1)
if(k & j)
{
if(handlermouse2buttons & j)
event.type=ev_keydown;
else
event.type=ev_keyup;
event.data1=KEY_2MOUSE1+i;
D_PostEvent(&event);
}
}
if ((handlermouse2x!=0)||(handlermouse2y!=0))
{
event.type=ev_mouse2;
event.data1=0;
// event.data1=buttons; // not needed
event.data2=handlermouse2x<<1;
event.data3=-handlermouse2y<<1;
D_PostEvent(&event);
handlermouse2x=0;
handlermouse2y=0;
}
}
#endif
if(mouse_detected)
{
//mouse movement
int xmickeys,ymickeys,buttons;
static int lastbuttons=0;
r.x.ax=0x0b; // ask the mouvement not the position
__dpmi_int(0x33,&r);
xmickeys=(signed short)r.x.cx;
ymickeys=(signed short)r.x.dx;
r.x.ax=0x03;
__dpmi_int(0x33,&r);
buttons=r.x.bx;
// post key event for buttons
if (buttons!=lastbuttons)
{
int j=1,k;
k=(buttons ^ lastbuttons); // only changed bit to 1
lastbuttons=buttons;
for(i=0;i<MOUSEBUTTONS;i++,j<<=1)
if(k & j)
{
if(buttons & j)
event.type=ev_keydown;
else
event.type=ev_keyup;
event.data1=KEY_MOUSE1+i;
D_PostEvent(&event);
}
}
if ((xmickeys!=0)||(ymickeys!=0))
{
event.type=ev_mouse;
event.data1=0;
// event.data1=buttons; // not needed
event.data2=xmickeys;
event.data3=-ymickeys;
D_PostEvent(&event);
}
}
//joystick
if (joystick_detected)
{
static int lastjoybuttons=0;
int joybuttons;
poll_joystick();
// I assume that true is 1
joybuttons=joy_b1+(joy_b2<<1)+(joy_b3<<2)+(joy_b4<<3)
+(joy_b5<<4)+(joy_b6<<5)+(joy_b7<<6)+(joy_b8<<7);
switch(joy_hat) {
case JOY_HAT_UP : joybuttons|=1<<10;break;
case JOY_HAT_DOWN : joybuttons|=1<<11;break;
case JOY_HAT_LEFT : joybuttons|=1<<12;break;
case JOY_HAT_RIGHT: joybuttons|=1<<13;break;
}
// post key event for buttons
if(joybuttons!=lastjoybuttons)
{
int j=1,k;
k=(joybuttons ^ lastjoybuttons); // only changed bit to 1
lastjoybuttons=joybuttons;
for(i=0;i<JOYBUTTONS;i++,j<<=1)
if(k & j) // test the eatch bit and post the corresponding event
{
if(joybuttons & j)
event.type=ev_keydown;
else
event.type=ev_keyup;
event.data1=KEY_JOY1+i;
D_PostEvent(&event);
}
}
event.type=ev_joystick;
event.data1=0;
event.data2=0;
event.data3=0;
if(joy_left)
event.data2=-1;
if(joy_right)
event.data2=1;
if(joy_up)
event.data3=-1;
if(joy_down)
event.data3=1;
D_PostEvent(&event);
}
}
//
// Timer user routine called at ticrate.
//
void I_TimerISR (void)
{
// IO_PlayerInput(); // old doom did that
ticcount++;
}
END_OF_FUNCTION(I_TimerISR);
//added:08-01-98: we don't use allegro_exit() so we have to do it ourselves.
void I_ShutdownTimer (void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -