📄 i_system.c
字号:
// Emacs style mode select -*- C++ -*-//-----------------------------------------------------------------------------//// $Id: i_system.c,v 1.7 2001/03/12 21:03:10 metzgermeister Exp $//// Copyright (C) 1993-1996 by id Software, Inc.// Portions Copyright (C) 1998-2000 by DooM Legacy Team.//// 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.////// $Log: i_system.c,v $// Revision 1.7 2001/03/12 21:03:10 metzgermeister// * new symbols for rendererlib added in SDL// * console printout fixed for Linux&SDL// * Crash fixed in Linux SW renderer initialization//// Revision 1.6 2001/02/24 13:35:23 bpereira// no message//// Revision 1.5 2000/11/02 19:49:40 bpereira// no message//// Revision 1.4 2000/10/16 21:20:53 hurdler// remove unecessary code//// Revision 1.3 2000/09/26 17:58:06 metzgermeister// I_Getkey implemented//// Revision 1.2 2000/09/10 10:56:00 metzgermeister// clean up & made it work again//// Revision 1.1 2000/08/21 21:17:32 metzgermeister// Initial import to CVS//////// DESCRIPTION:////-----------------------------------------------------------------------------#include <stdio.h>#include <stdlib.h>#include <string.h>#include <SDL/SDL.h>#ifdef LINUX#include <sys/vfs.h>#endif#ifdef LMOUSE2#include <termios.h>#endif#ifdef LJOYSTICK // linux joystick 1.x#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <fcntl.h>#include <linux/joystick.h>#endif#include "doomdef.h"#include "m_misc.h"#include "i_video.h"#include "i_sound.h"#include "i_system.h"#include "d_net.h"#include "g_game.h"#include "endtxt.h"#include "i_joy.h"extern void D_PostEvent(event_t*);#ifdef LJOYSTICKint joyfd = -1;int joyaxes = 0;int joystick_started = 0;int joy_scale = 1;#endifJoyType_t Joystick;#ifdef LMOUSE2int fdmouse2 = -1;int mouse2_started = 0;#endifbyte keyboard_started = 0;void I_StartupKeyboard (void) {}void I_StartupTimer (void) {}void I_OutputMsg (char *fmt, ...) { va_list argptr; va_start (argptr,fmt); vfprintf (stderr,fmt,argptr); va_end (argptr);}int I_GetKey (void){ // Warning: I_GetKey emties the event queue till next keypress event_t* ev; int rc=0; // return the first keypress from the event queue for ( ; eventtail != eventhead ; eventtail = (++eventtail)&(MAXEVENTS-1) ) { ev = &events[eventtail]; if(ev->type == ev_keydown) { rc = ev->data1; continue; } } return rc;}#ifdef LJOYSTICKvoid I_JoyScale() { joy_scale = (cv_joyscale.value==0)?1:cv_joyscale.value;}void I_GetJoyEvent() { struct js_event jdata; static event_t event = {0,0,0,0}; static int buttons = 0; if(!joystick_started) return; while(read(joyfd,&jdata,sizeof(jdata))!=-1) { switch(jdata.type) { case JS_EVENT_AXIS: event.type = ev_joystick; event.data1 = 0; switch(jdata.number) { case 0: event.data2 = ((jdata.value >> 5)/joy_scale)*joy_scale; D_PostEvent(&event); break; case 1: event.data3 = ((jdata.value >> 5)/joy_scale)*joy_scale; D_PostEvent(&event); default: break; } break; case JS_EVENT_BUTTON: if(jdata.number<JOYBUTTONS) { if(jdata.value) { if(!((buttons >> jdata.number)&1)) { buttons |= 1 << jdata.number; event.type = ev_keydown; event.data1 = KEY_JOY1+jdata.number; D_PostEvent(&event); } } else { if((buttons>>jdata.number)&1) { buttons ^= 1 << jdata.number; event.type = ev_keyup; event.data1 = KEY_JOY1+jdata.number; D_PostEvent(&event); } } } break; } }}void I_ShutdownJoystick() { if(joyfd!=-1) { close(joyfd); joyfd = -1; } joyaxes = 0; joystick_started = 0;}int joy_open(char *fname) { joyfd = open(fname,O_RDONLY|O_NONBLOCK); if(joyfd==-1) { CONS_Printf("Error opening %s!\n",fname); return 0; } ioctl(joyfd,JSIOCGAXES,&joyaxes); if(joyaxes<2) { CONS_Printf("Not enought axes?\n"); joyaxes = 0; joyfd = -1; close(joyfd); return 0; } return joyaxes;}/*int joy_waitb(int fd, int *xpos,int *ypos,int *hxpos,int *hypos) { int i,xps,yps,hxps,hyps; struct js_event jdata; for(i=0;i<1000;i++) { while(read(fd,&jdata,sizeof(jdata))!=-1) { switch(jdata.type) { case JS_EVENT_AXIS: switch(jdata.number) { case 0: // x xps = jdata.value; break; case 1: // y yps = jdata.value; break; case 3: // hat x hxps = jdata.value; break; case 4: // hat y hyps = jdata.value; default: break; } break; case JS_EVENT_BUTTON: break; } } } }*/#endif // LJOYSTICKvoid I_InitJoystick (void) {#ifdef LJOYSTICK I_ShutdownJoystick(); if(!strcmp(cv_usejoystick.string,"0")) return; if(!joy_open(cv_joyport.string)) return; joystick_started = 1; return;#endif}#ifdef LMOUSE2void I_GetMouse2Event() { static unsigned char mdata[5]; static int i = 0,om2b = 0; int di,j,mlp,button; event_t event; const int mswap[8] = {0,4,1,5,2,6,3,7}; if(!mouse2_started) return; for(mlp=0;mlp<20;mlp++) { for(;i<5;i++) { di = read(fdmouse2,mdata+i,1); if(di==-1) return; } if((mdata[0]&0xf8)!=0x80) { for(j=1;j<5;j++) { if((mdata[j]&0xf8)==0x80) { for(i=0;i<5-j;i++) { // shift mdata[i] = mdata[i+j]; } } } if(i<5) continue; } else { button = mswap[~mdata[0]&0x07]; for(j=0;j<MOUSEBUTTONS;j++) { if(om2b&(1<<j)) { if(!(button&(1<<j))) { //keyup event.type = ev_keyup; event.data1 = KEY_2MOUSE1+j; D_PostEvent(&event); om2b ^= 1 << j; } } else { if(button&(1<<j)) { event.type = ev_keydown; event.data1 = KEY_2MOUSE1+j; D_PostEvent(&event); om2b ^= 1 << j; } } } event.data2 = ((signed char)mdata[1])+((signed char)mdata[3]); event.data3 = ((signed char)mdata[2])+((signed char)mdata[4]); if(event.data2&&event.data3) { event.type = ev_mouse2; event.data1 = 0; D_PostEvent(&event); } } i = 0; }}void I_ShutdownMouse2() { if(fdmouse2!=-1) close(fdmouse2); mouse2_started = 0;}#endifvoid I_StartupMouse2 (void) {#ifdef LMOUSE2 struct termios m2tio; int i,dtr,rts; I_ShutdownMouse2(); if(cv_usemouse2.value == 0) return; if((fdmouse2 = open(cv_mouse2port.string,O_RDONLY|O_NONBLOCK|O_NOCTTY))==-1) { CONS_Printf("Error opening %s!\n",cv_mouse2port.string); return; } tcflush(fdmouse2, TCIOFLUSH); m2tio.c_iflag = IGNBRK; m2tio.c_oflag = 0; m2tio.c_cflag = CREAD|CLOCAL|HUPCL|CS8|CSTOPB|B1200; m2tio.c_lflag = 0; m2tio.c_cc[VTIME] = 0; m2tio.c_cc[VMIN] = 1; tcsetattr(fdmouse2, TCSANOW, &m2tio); strupr(cv_mouse2opt.string); for(i=0,rts = dtr = -1;i<strlen(cv_mouse2opt.string);i++) { if(cv_mouse2opt.string[i]=='D') { if(cv_mouse2opt.string[i+1]=='-') { dtr = 0; } else { dtr = 1; } } if(cv_mouse2opt.string[i]=='R') { if(cv_mouse2opt.string[i+1]=='-') { rts = 0; } else { rts = 1; } } } if((dtr!=-1)||(rts!=-1)) { if(!ioctl(fdmouse2, TIOCMGET, &i)) { if(!dtr) { i &= ~TIOCM_DTR; } else { if(dtr>0) i |= TIOCM_DTR; } if(!rts) { i &= ~TIOCM_RTS; } else { if(rts>0) i |= TIOCM_RTS; } ioctl(fdmouse2, TIOCMSET, &i); } } mouse2_started = 1;#endif}byte mb_used = 6+2; // 2 more for caching soundstatic int quiting=0; /* prevent recursive I_Quit() */void I_Tactile(int on,int off,int total ){ // UNUSED. on = off = total = 0;}ticcmd_t emptycmd;ticcmd_t* I_BaseTiccmd(void){ return &emptycmd;}int I_GetHeapSize (void){ return mb_used*1024*1024;}//// I_GetTime// returns time in 1/TICRATE second tics//ULONG I_GetTime (void){ Uint32 ticks; static Uint32 basetime=0; // milliseconds since SDL initialization ticks = SDL_GetTicks(); if (!basetime) basetime = ticks; return (ticks - basetime)*TICRATE/1000;}//// I_Init//void I_Init (void){ I_StartupSound(); I_InitMusic(); quiting = 0;}//// I_Quit//void I_Quit (void){ /* prevent recursive I_Quit() */ if(quiting) return; quiting = 1; //added:16-02-98: when recording a demo, should exit using 'q' key, // but sometimes we forget and use 'F10'.. so save here too. if (demorecording) G_CheckDemoStatus(); D_QuitNetGame (); I_ShutdownMusic(); I_ShutdownSound(); I_ShutdownCD(); // use this for 1.28 19990220 by Kin M_SaveConfig (NULL); I_ShutdownGraphics(); I_ShutdownSystem(); printf("\r"); ShowEndTxt(); exit(0);}void I_WaitVBL(int count){ SDL_Delay(1);}void I_BeginRead(void){}void I_EndRead(void){}byte* I_AllocLow(int length){ byte* mem; mem = (byte *)malloc (length); memset (mem,0,length); return mem;}//// I_Error//extern boolean demorecording;void I_Error (char *error, ...){ va_list argptr; // Message first. va_start (argptr,error); fprintf (stderr, "Error: "); vfprintf (stderr,error,argptr); fprintf (stderr, "\n"); va_end (argptr); fflush( stderr ); // Shutdown. Here might be other errors. if (demorecording) G_CheckDemoStatus(); D_QuitNetGame (); I_ShutdownMusic(); I_ShutdownSound(); I_ShutdownGraphics(); // shutdown everything else which was registered I_ShutdownSystem(); exit(-1);}#define MAX_QUIT_FUNCS 16typedef void (*quitfuncptr)();static quitfuncptr quit_funcs[MAX_QUIT_FUNCS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };//// Adds a function to the list that need to be called by I_SystemShutdown().//void I_AddExitFunc(void (*func)()){ int c; for (c=0; c<MAX_QUIT_FUNCS; c++) { if (!quit_funcs[c]) { quit_funcs[c] = func; break; } }}//// Removes a function from the list that need to be called by// I_SystemShutdown().//void I_RemoveExitFunc(void (*func)()){ int c; for (c=0; c<MAX_QUIT_FUNCS; c++) { if (quit_funcs[c] == func) { while (c<MAX_QUIT_FUNCS-1) { quit_funcs[c] = quit_funcs[c+1]; c++; } quit_funcs[MAX_QUIT_FUNCS-1] = NULL; break; } }}//// Closes down everything. This includes restoring the initial// pallete and video mode, and removing whatever mouse, keyboard, and// timer routines have been installed.//// NOTE : Shutdown user funcs. are effectively called in reverse order.//void I_ShutdownSystem(){ int c; for (c=MAX_QUIT_FUNCS-1; c>=0; c--) if (quit_funcs[c]) (*quit_funcs[c])();}void I_GetDiskFreeSpace(long long *freespace) {#ifdef LINUX struct statfs stfs; if(statfs(".",&stfs)==-1) { *freespace = MAXINT; return; } *freespace = stfs.f_bavail*stfs.f_bsize;#endif#ifdef __WIN32__ static MyFunc pfnGetDiskFreeSpaceEx=NULL; static boolean testwin95 = false; INT64 usedbytes; if(!testwin95) { HINSTANCE h = LoadLibraryA("kernel32.dll"); if (h) { pfnGetDiskFreeSpaceEx = (MyFunc)GetProcAddress(h,"GetDiskFreeSpaceExA"); FreeLibrary(h); } testwin95 = true; } if (pfnGetDiskFreeSpaceEx) { if (!pfnGetDiskFreeSpaceEx(NULL,(PULARGE_INTEGER)freespace,(PULARGE_INTEGER)&usedbytes,NULL)) *freespace = MAXINT; } else { ULONG SectorsPerCluster, BytesPerSector, NumberOfFreeClusters; ULONG TotalNumberOfClusters; GetDiskFreeSpace(NULL, &SectorsPerCluster, &BytesPerSector, &NumberOfFreeClusters, &TotalNumberOfClusters); *freespace = BytesPerSector*SectorsPerCluster*NumberOfFreeClusters; }#endif#if !defined (LINUX) && !defined (__WIN32__) // Dummy for platform independent; 1GB should be enough *freespace = 1024*1024*1024;#endif}char *I_GetUserName(void){#ifdef LINUX static char username[MAXPLAYERNAME]; char *p; if((p=getenv("USER"))==NULL) if((p=getenv("user"))==NULL) if((p=getenv("USERNAME"))==NULL) if((p=getenv("username"))==NULL) return NULL; strncpy(username,p,MAXPLAYERNAME); if( strcmp(username,"")==0 ) return NULL; return username;#endif#ifdef __WIN32__ static char username[MAXPLAYERNAME]; char *p; int ret; ULONG i=MAXPLAYERNAME; ret = GetUserName(username,&i); if(!ret) { if((p=getenv("USER"))==NULL) if((p=getenv("user"))==NULL) if((p=getenv("USERNAME"))==NULL) if((p=getenv("username"))==NULL) return NULL; strncpy(username,p,MAXPLAYERNAME); } if( strcmp(username,"")==0 ) return NULL; return username;#endif#if !defined (LINUX) && !defined (__WIN32__) // dummy for platform independent version return NULL;#endif}int I_mkdir(const char *dirname, int unixright){#ifdef LINUX return mkdir(dirname, unixright);#else return mkdir(dirname);#endif}void I_LocateWad(void) { // relict from the Linux version return;}// quick fix for compilULONG I_GetFreeMem(ULONG *total){ return 16<<20;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -