home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / server / sys_amiga.c < prev    next >
C/C++ Source or Header  |  2000-06-17  |  10KB  |  497 lines

  1. /* 
  2. Copyright (C) 1996-1997 Id Software, Inc. 
  3.  
  4. This program is free software; you can redistribute it and/or 
  5. modify it under the terms of the GNU General Public License 
  6. as published by the Free Software Foundation; either version 2 
  7. of the License, or (at your option) any later version. 
  8.  
  9. This program is distributed in the hope that it will be useful, 
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of 
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   
  12.  
  13. See the GNU General Public License for more details. 
  14.  
  15. You should have received a copy of the GNU General Public License 
  16. along with this program; if not, write to the Free Software 
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
  18.  
  19. */ 
  20.  
  21. /*
  22. ** sys_amiga.c
  23. **
  24. ** QuakeWorld Server for Amiga M68k and Amiga PowerPC
  25. **
  26. */
  27.  
  28. #pragma amiga-align
  29. #include <exec/types.h>
  30. #include <exec/memory.h>
  31. #include <exec/execbase.h>
  32. #include <dos/dos.h>
  33. #include <utility/tagitem.h>
  34. #include <graphics/gfxbase.h>
  35. #include <devices/timer.h>
  36. #include <clib/alib_protos.h>
  37. #include <proto/exec.h>
  38. #include <proto/dos.h>
  39. #include <proto/timer.h>
  40. #ifdef __PPC__
  41. #ifdef WOS
  42. #include <clib/powerpc_protos.h>
  43. #else
  44. #include <powerup/ppclib/time.h>
  45. #include <powerup/gcclib/powerup_protos.h>
  46. #endif
  47. #endif
  48. #pragma default-align
  49.  
  50. /* Quake includes */
  51. #include "qwsvdef.h"
  52.  
  53.  
  54. cvar_t sys_nostdout = {"sys_nostdout","0"};
  55. cvar_t sys_extrasleep = {"sys_extrasleep","0"};
  56. static quakeparms_t parms;
  57. struct Library *TimerBase = NULL;
  58.  
  59. static struct timerequest *timerio;
  60. static int membase_offs;
  61. static BPTR amiga_stdin,amiga_stdout;
  62.  
  63. extern void NET_Select(unsigned long);
  64.  
  65.  
  66. /*
  67.  * AMIGA only functions
  68.  */
  69.  
  70. #if defined(__PPC__) && !defined(WOS)
  71. /*
  72.  * This is a GetSysTimePPC-emulation for PowerUp, as calling
  73.  * M68k-GetSysTime() via context switch needs too much time.
  74.  */
  75. static void *PowerUpTimer = NULL;
  76. static ULONG TicksPerSec[2];
  77.  
  78.  
  79. /*
  80. ================
  81. InitSysTimePPC
  82. ================
  83. */
  84. static void InitSysTimePPC(void)
  85. {
  86.   struct TagItem ti[2];
  87.   ULONG r[2];
  88.  
  89.   ti[0].ti_Tag = PPCTIMERTAG_CPU;
  90.   ti[0].ti_Data = TRUE;
  91.   ti[1].ti_Tag = TAG_END;
  92.   if (!(PowerUpTimer = PPCCreateTimerObject(ti)))
  93.     Sys_Error("Can't create TimerObject");
  94.   PPCGetTimerObject(PowerUpTimer,PPCTIMERTAG_TICKSPERSEC,TicksPerSec);
  95. }
  96.  
  97. /*
  98. ================
  99. ExitSysTimePPC
  100. ================
  101. */
  102. static void ExitSysTimePPC(void)
  103. {
  104.   if (PowerUpTimer) {
  105.     PPCDeleteTimerObject(PowerUpTimer);
  106.     PowerUpTimer = NULL;
  107.   }
  108. }
  109.  
  110. /*
  111. ================
  112. GetSysTimePPC
  113. ================
  114. */
  115. void GetSysTimePPC(struct timeval *tv)
  116. {
  117.   static ULONG mill[2] = { 0,1000000 };
  118.   ULONG r[2],secs[2];
  119.  
  120.   if (PowerUpTimer) {
  121.     PPCGetTimerObject(PowerUpTimer,PPCTIMERTAG_CURRENTTICKS,r);
  122.     secs[0] = r[0];
  123.     secs[1] = r[1];
  124.     PPCDivu64p((int *)secs,(int *)TicksPerSec);
  125.     tv->tv_secs = secs[1];
  126.     PPCModu64p((int *)r,(int *)TicksPerSec);
  127.     PPCMulu64p((int *)r,(int *)mill);
  128.     PPCDivu64p((int *)r,(int *)TicksPerSec);
  129.     tv->tv_micro = r[1];
  130.   }
  131. }
  132. #endif
  133.  
  134.  
  135. /*
  136. ================
  137. cleanup
  138. ================
  139. */
  140. static void cleanup(int rc)
  141. {
  142.   SetMode(amiga_stdin,0);  /* put console back into normal CON mode */
  143.  
  144.   if (parms.membase)
  145.     FreeMem((char *)parms.membase-membase_offs,parms.memsize+3*32);
  146.  
  147.   if (TimerBase) {
  148.     if (!CheckIO((struct IORequest *)timerio)) {
  149.       AbortIO((struct IORequest *)timerio);
  150.       WaitIO((struct IORequest *)timerio);
  151.     }
  152.     CloseDevice((struct IORequest *)timerio);
  153.     DeletePort(timerio->tr_node.io_Message.mn_ReplyPort);
  154.     DeleteExtIO((struct IORequest *)timerio);
  155.   }
  156.  
  157. #if defined(__PPC__) && !defined(WOS)
  158.   /* cleanup GetSysTimePPC() emulation for PowerUp */
  159.   ExitSysTimePPC();
  160. #endif
  161.  
  162.   exit(rc);
  163. }
  164.  
  165.  
  166. /*
  167. ================
  168. usleep
  169. ================
  170. */
  171. void usleep(unsigned long timeout)
  172. {
  173.   timerio->tr_node.io_Command = TR_ADDREQUEST;
  174.   timerio->tr_time.tv_secs = timeout / 1000000;
  175.   timerio->tr_time.tv_micro = timeout % 1000000;
  176.   SendIO((struct IORequest *)timerio);
  177.   WaitIO((struct IORequest *)timerio);
  178. }
  179.  
  180.  
  181. /*
  182. ================
  183. strcasecmp
  184. ================
  185. */
  186. int strcasecmp(const char *str1, const char *str2)
  187. {
  188.   while(tolower((unsigned char)*str1) == tolower((unsigned char)*str2)) {
  189.     if(!*str1) return(0);
  190.     str1++;str2++;
  191.   }
  192.   return(tolower(*(unsigned char *)str1)-tolower(*(unsigned char *)str2));
  193. }
  194.  
  195.  
  196. /*
  197. ================
  198. strncasecmp
  199. ================
  200. */
  201. int strncasecmp(const char *str1, const char *str2, size_t n)
  202. {
  203.   if (n==0) return 0;
  204.   while (--n && tolower((unsigned char)*str1)==tolower((unsigned char)*str2)){
  205.     if (!*str1) return(0);
  206.     str1++; str2++;
  207.   }
  208.   return(tolower(*(unsigned char *)str1)-tolower(*(unsigned char *)str2));
  209. }
  210.  
  211.  
  212. /*
  213. ================
  214. bzero
  215. ================
  216. */
  217. void bzero(void *p,size_t n)
  218. {
  219.   memset(p,0,n);
  220. }
  221.  
  222.  
  223. /*
  224. ===============================================================================
  225.  
  226.         REQUIRED SYS FUNCTIONS
  227.  
  228. ===============================================================================
  229. */
  230.  
  231. /*
  232. ============
  233. Sys_FileTime
  234.  
  235. returns -1 if not present
  236. ============
  237. */
  238. int Sys_FileTime (char *path)
  239. {
  240.   BPTR lck;
  241.   int  t = -1;
  242.  
  243.   if (lck = Lock(path,ACCESS_READ)) {
  244.     t = 1;
  245.     UnLock(lck);
  246.   }
  247.  
  248.   return t;
  249. }
  250.  
  251.  
  252. /*
  253. ============
  254. Sys_mkdir
  255.  
  256. ============
  257. */
  258. void Sys_mkdir (char *path)
  259. {
  260.   BPTR lck;
  261.  
  262.   if (lck = CreateDir(path))
  263.     UnLock(lck);
  264. }
  265.  
  266.  
  267. /*
  268. ================
  269. Sys_DoubleTime
  270. ================
  271. */
  272. double Sys_DoubleTime (void)
  273. {
  274.   static ULONG secbase = 0;
  275.   struct timeval tv;
  276.  
  277. #ifdef __PPC__
  278.   GetSysTimePPC(&tv);
  279. #else
  280.   GetSysTime(&tv);
  281. #endif
  282.   if (!secbase) {
  283.     secbase = tv.tv_secs;
  284.     return (double)tv.tv_micro/1000000.0;
  285.   }
  286.   return (double)(tv.tv_secs-secbase) + (((double)tv.tv_micro) / 1000000.0);
  287. }
  288.  
  289. /*
  290. ================
  291. Sys_Error
  292. ================
  293. */
  294. void Sys_Error (char *error, ...)
  295. {
  296.   va_list argptr;
  297.   
  298.   printf("Fatal error: ");
  299.   va_start(argptr,error);
  300.   vprintf(error,argptr);
  301.   va_end(argptr);
  302.   printf("\n");
  303.   cleanup(1);
  304. }
  305.  
  306. /*
  307. ================
  308. Sys_Printf
  309. ================
  310. */
  311. void Sys_Printf (char *fmt, ...)
  312. {
  313.   va_list argptr;
  314.   static char text[2048];
  315.   unsigned char *p;
  316.  
  317.   va_start(argptr,fmt);
  318.   vsprintf(text,fmt,argptr);
  319.   va_end(argptr);
  320.  
  321.   if (strlen(text) > sizeof(text))
  322.     Sys_Error("memory overwrite in Sys_Printf");
  323.  
  324.   if (sys_nostdout.value)
  325.     return;
  326.  
  327.   for (p = (unsigned char *)text; *p; p++) {
  328.     *p &= 0x7f;
  329.     if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9)
  330.       printf("[%02x]", *p);
  331.     else
  332.       putc(*p, stdout);
  333.   }
  334.   fflush(stdout);
  335. }
  336.  
  337.  
  338. /*
  339. ================
  340. Sys_Quit
  341. ================
  342. */
  343. void Sys_Quit (void)
  344. {
  345.   cleanup(0);   // appkit isn't running
  346. }
  347.  
  348.  
  349. /*
  350. ================
  351. Sys_ConsoleInput
  352.  
  353. Checks for a complete line of text typed in at the console, then forwards
  354. it to the host command processor
  355. ================
  356. */
  357. char *Sys_ConsoleInput (void)
  358. {
  359.   static const char *backspace = "\b \b";
  360.   static char text[256];
  361.   static int len = 0;
  362.   char ch;
  363.  
  364.   while (WaitForChar(amiga_stdin,10) == DOSTRUE) {
  365.     Read(amiga_stdin,&ch,1);  /* note: console is in RAW mode! */
  366.     if (ch == '\r') {
  367.       ch = '\n';
  368.       Write(amiga_stdout,&ch,1);
  369.       text[len] = 0;
  370.       len = 0;
  371.       return text;
  372.     }
  373.     else if (ch == '\b') {
  374.       if (len > 0) {
  375.         len--;
  376.         Write(amiga_stdout,(char *)backspace,3);
  377.       }
  378.     }
  379.     else {
  380.       if (len < sizeof(text)-1) {
  381.         Write(amiga_stdout,&ch,1);
  382.         text[len++] = ch;
  383.       }
  384.     }
  385.   }
  386.   return NULL;
  387. }
  388.  
  389. /*
  390. =============
  391. Sys_Init
  392.  
  393. Quake calls this so the system can register variables before host_hunklevel
  394. is marked
  395. =============
  396. */
  397. void Sys_Init (void)
  398. {
  399.   Cvar_RegisterVariable (&sys_nostdout);
  400.   Cvar_RegisterVariable (&sys_extrasleep);
  401. }
  402.  
  403. /*
  404. =============
  405. main
  406. =============
  407. */
  408. main(int argc, char *argv[])
  409. {
  410.   char cwd[128];
  411.   struct MsgPort *timerport;
  412.   int i;
  413.   double time, oldtime, newtime;
  414.  
  415.   memset(&parms,0,sizeof(parms));
  416.   parms.memsize = 16*1024*1024;  /* 16MB is default */
  417.  
  418.   COM_InitArgv (argc, argv);  
  419.   parms.argc = com_argc;
  420.   parms.argv = com_argv;
  421.  
  422.   /* Amiga Init */
  423.   amiga_stdin = Input();
  424.   amiga_stdout = Output();
  425.   if (!COM_CheckParm("-noconsole"))
  426.     SetMode(amiga_stdin,1);  /* put console into RAW mode */
  427.  
  428. #if defined(__PPC__) && !defined(WOS)
  429.   /* init GetSysTimePPC() emulation for PowerUp */
  430.   InitSysTimePPC();
  431. #endif
  432.  
  433.   /* open timer.device */
  434.   if (timerport = CreatePort(NULL,0)) {
  435.     if (timerio = (struct timerequest *)
  436.                    CreateExtIO(timerport,sizeof(struct timerequest))) {
  437.       if (OpenDevice(TIMERNAME,UNIT_MICROHZ,
  438.                      (struct IORequest *)timerio,0) == 0) {
  439.         TimerBase = (struct Library *)timerio->tr_node.io_Device;
  440.       }
  441.       else {
  442.         DeleteExtIO((struct IORequest *)timerio);
  443.         DeletePort(timerport);
  444.       }
  445.     }
  446.     else
  447.       DeletePort(timerport);
  448.   }
  449.   if (!TimerBase)
  450.     Sys_Error("Can't open timer.device");
  451.   usleep(1);  /* don't delete, otherwise we can't do timer.device cleanup */
  452.  
  453.   /* check arguments */
  454.   if (i = COM_CheckParm("-mem"))
  455.     parms.memsize = (int)(Q_atof(com_argv[i+1]) * 1024 * 1024);
  456.  
  457.   /* alloc 16-byte aligned quake memory */
  458.   parms.memsize = (parms.memsize+15)&~15;
  459.   if ((parms.membase = AllocMem((ULONG)parms.memsize,MEMF_FAST)) == NULL)
  460.     Sys_Error("Can't allocate %ld bytes\n", parms.memsize);
  461.   if ((ULONG)parms.membase & 8)
  462.     membase_offs = 40;  /* guarantee 16-byte aligment */
  463.   else
  464.     membase_offs = 32;
  465.   parms.membase = (char *)parms.membase + membase_offs;
  466.   parms.memsize -= 3*32;
  467.  
  468.   /* get name of current directory */
  469.   GetCurrentDirName(cwd,128);
  470.   parms.basedir = cwd;
  471.  
  472.   SV_Init (&parms);
  473.  
  474.   /* run one frame immediately for first heartbeat */
  475.   SV_Frame (0.1);
  476.  
  477. /*
  478.  * main loop
  479.  */
  480.   oldtime = Sys_DoubleTime() - 0.1;
  481.   while (1) {
  482.     /* wait 100 usec for a pending network packet */
  483.     NET_Select(100);
  484.  
  485.     /* find time passed since last cycle */
  486.     newtime = Sys_DoubleTime();
  487.     time = newtime - oldtime;
  488.     oldtime = newtime;
  489.  
  490.     SV_Frame (time);    
  491.     
  492.     /* extrasleep is just a way to generate a fucked up connection on purpose */
  493.     if (sys_extrasleep.value)
  494.       usleep(sys_extrasleep.value);
  495.   }
  496. }
  497.