home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / glquake_src / sys_amiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-06  |  13.6 KB  |  636 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. ** Quake for Amiga M68k and Amiga PowerPC
  25. **
  26. ** Written by Frank Wille <frank@phoenix.owl.de>
  27. **
  28. */
  29.  
  30. #include <exec/types.h>
  31. #include <exec/memory.h>
  32. #include <exec/execbase.h>
  33. #include <dos/dos.h>
  34. #include <utility/tagitem.h>
  35. #include <graphics/gfxbase.h>
  36. #include <devices/timer.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.  
  49. #include "quakedef.h"
  50.  
  51. #define MAX_HANDLES     10
  52. #define CLOCK_PAL       3546895
  53. #define CLOCK_NTSC      3579545
  54.  
  55. #ifdef __STORM__
  56. extern struct Library *TimerBase;
  57. extern struct Library *UtilityBase;
  58. #else
  59. struct Library *TimerBase = NULL;
  60. struct Library *UtilityBase = NULL;
  61. #endif
  62. struct Library *LowLevelBase = NULL;
  63. #ifdef __PPC__
  64. #ifdef __STORM__
  65. extern struct Library *MathIeeeDoubBasBase = NULL;
  66. #else
  67. struct Library *MathIeeeDoubBasBase;
  68. #endif
  69. qboolean no68kFPU = false; /* for LC040/LC060 systems */
  70. #endif
  71. qboolean isDedicated = false;
  72. long sysclock = CLOCK_PAL;
  73. int FirstTime = 0;
  74. int FirstTime2 = 0;
  75.  
  76. static BPTR amiga_stdin,amiga_stdout;
  77. static BPTR sys_handles[MAX_HANDLES];
  78. static struct timerequest *timerio;
  79. static int membase_offs = 32;
  80. static int nostdout=1, coninput=0;
  81.  
  82. //#ifndef __PPC__
  83. //extern void MMUHackOn(void);
  84. //extern void MMUHackOff(void);
  85. //#endif
  86.  
  87.  
  88. /*
  89. ===============================================================================
  90.  
  91. FILE IO
  92.  
  93. ===============================================================================
  94. */
  95.  
  96. static int findhandle (void)
  97. {
  98.   int i;
  99.   
  100.   for (i=1 ; i<MAX_HANDLES ; i++)
  101.     if (!sys_handles[i])
  102.       return i;
  103.   Sys_Error ("out of handles");
  104.   return -1;
  105. }
  106.  
  107. int Sys_FileOpenRead (char *path, int *hndl)
  108. {
  109.   BPTR fh;
  110.   struct FileInfoBlock *fib;
  111.   int     i = -1;
  112.   int flen = -1;
  113.   
  114.   *hndl = -1;
  115.   if (fib = AllocDosObjectTags(DOS_FIB,TAG_DONE)) {
  116.     if (fh = Open(path,MODE_OLDFILE)) {
  117.       if (ExamineFH(fh,fib)) {
  118.         if ((i = findhandle()) > 0) {
  119.           sys_handles[i] = fh;
  120.           *hndl = i;
  121.           flen = (int)fib->fib_Size;
  122.         }
  123.         else
  124.           Close(fh);
  125.       }
  126.       else
  127.         Close(fh);
  128.     }
  129.     FreeDosObject(DOS_FIB,fib);
  130.   }
  131.   return flen;
  132. }
  133.  
  134. int Sys_FileOpenWrite (char *path)
  135. {
  136.   BPTR fh;
  137.   int  i;
  138.   
  139.   if ((i = findhandle ()) > 0) {
  140.     if (fh = Open(path,MODE_NEWFILE)) {
  141.       sys_handles[i] = fh;
  142.     }
  143.     else {
  144.       char ebuf[80];
  145.       Fault(IoErr(),"",ebuf,80);
  146.       Sys_Error ("Error opening %s: %s", path, ebuf);
  147.       i = -1;
  148.     }
  149.   }
  150.   return i;
  151. }
  152.  
  153. void Sys_FileClose (int handle)
  154. {
  155.   if (sys_handles[handle]) {
  156.     Close(sys_handles[handle]);
  157.     sys_handles[handle] = 0;
  158.   }
  159. }
  160.  
  161. void Sys_FileSeek (int handle, int position)
  162. {
  163.   Seek(sys_handles[handle],position,OFFSET_BEGINNING);
  164. }
  165.  
  166. int Sys_FileRead (int handle, void *dest, int count)
  167. {
  168.   return (int)Read(sys_handles[handle],dest,(LONG)count);
  169. }
  170.  
  171. int Sys_FileWrite (int handle, void *data, int count)
  172. {
  173.   return (int)Write(sys_handles[handle],data,(LONG)count);
  174. }
  175.  
  176. int Sys_FileTime (char *path)
  177. {
  178.   BPTR lck;
  179.   int  t = -1;
  180.  
  181.   if (lck = Lock(path,ACCESS_READ)) {
  182.     t = 1;
  183.     UnLock(lck);
  184.   }
  185.  
  186.   return t;
  187. }
  188.  
  189. void Sys_mkdir (char *path)
  190. {
  191.   BPTR lck;
  192.  
  193.   if (lck = CreateDir(path))
  194.     UnLock(lck);
  195. }
  196.  
  197.  
  198. /*
  199. ===============================================================================
  200.  
  201. SYSTEM Functions
  202.  
  203. ===============================================================================
  204. */
  205.  
  206.  
  207. #if defined(__PPC__) && !defined(WOS)
  208. /*
  209.  * This is a GetSysTimePPC-emulation for PowerUp, as calling
  210.  * M68k-GetSysTime() via context switch needs too much time.
  211.  */
  212. static void *PowerUpTimer = NULL;
  213. static ULONG TicksPerSec[2];
  214.  
  215.  
  216. static void InitSysTimePPC(void)
  217. {
  218.   struct TagItem ti[2];
  219.  
  220.   ti[0].ti_Tag = PPCTIMERTAG_CPU;
  221.   ti[0].ti_Data = TRUE;
  222.   ti[1].ti_Tag = TAG_END;
  223.   if (!(PowerUpTimer = PPCCreateTimerObject(ti)))
  224.     Sys_Error("Can't create TimerObject");
  225.   PPCGetTimerObject(PowerUpTimer,PPCTIMERTAG_TICKSPERSEC,TicksPerSec);
  226.  
  227.   if (COM_CheckParm("-bppctimerfix")) {
  228.     /* fixes timer problem with bad BPPC flash ROM */
  229.     static ULONG factor[2] = { 0,2 };
  230.  
  231.     PPCDivu64p((int *)TicksPerSec,(int *)factor);
  232.   }   
  233. }
  234.  
  235. static void ExitSysTimePPC(void)
  236. {
  237.   if (PowerUpTimer) {
  238.     PPCDeleteTimerObject(PowerUpTimer);
  239.     PowerUpTimer = NULL;
  240.   }
  241. }
  242.  
  243. void GetSysTimePPC(struct timeval *tv)
  244. {
  245.   static ULONG mill[2] = { 0,1000000 };
  246.   ULONG r[2],secs[2];
  247.  
  248.   if (PowerUpTimer) {
  249.     PPCGetTimerObject(PowerUpTimer,PPCTIMERTAG_CURRENTTICKS,r);
  250.     secs[0] = r[0];
  251.     secs[1] = r[1];
  252.     PPCDivu64p((int *)secs,(int *)TicksPerSec);
  253.     tv->tv_secs = secs[1];
  254.     PPCModu64p((int *)r,(int *)TicksPerSec);
  255.     PPCMulu64p((int *)r,(int *)mill);
  256.     PPCDivu64p((int *)r,(int *)TicksPerSec);
  257.     tv->tv_micro = r[1];
  258.   }
  259. }
  260. #endif
  261.  
  262.  
  263. /*
  264. ================
  265. usleep
  266. ================
  267. */
  268. void usleep(unsigned long timeout)
  269. {
  270.   timerio->tr_node.io_Command = TR_ADDREQUEST;
  271.   timerio->tr_time.tv_secs = timeout / 1000000;
  272.   timerio->tr_time.tv_micro = timeout % 1000000;
  273.   SendIO((struct IORequest *)timerio);
  274.   WaitIO((struct IORequest *)timerio);
  275. }
  276.  
  277. /*
  278. ================
  279. strcasecmp
  280. ================
  281. */
  282. int strcasecmp(const char *str1, const char *str2)
  283. {
  284.   while(tolower((unsigned char)*str1) == tolower((unsigned char)*str2)) {
  285.     if(!*str1) return(0);
  286.     str1++;str2++;
  287.   }
  288.   return(tolower(*(unsigned char *)str1)-tolower(*(unsigned char *)str2));
  289. }
  290.  
  291. /*
  292. ================
  293. strncasecmp
  294. ================
  295. */
  296. int strncasecmp(const char *str1, const char *str2, size_t n)
  297. {
  298.   if (n==0) return 0;
  299.   while (--n && tolower((unsigned char)*str1)==tolower((unsigned char)*str2)){
  300.     if (!*str1) return(0);
  301.     str1++; str2++;
  302.   }
  303.   return(tolower(*(unsigned char *)str1)-tolower(*(unsigned char *)str2));
  304. }
  305.  
  306.  
  307. static void cleanup(int rc)
  308. {
  309.   int i;
  310.   Host_Shutdown();
  311.  
  312.   if (coninput) 
  313.     SetMode(amiga_stdin,0);  /* put console back into normal CON mode */
  314.     
  315.     
  316. #ifdef WOS
  317.   if (host_parms.membase) 
  318.     FreeVecPPC(host_parms.membase);  
  319. #else
  320.   if (host_parms.membase)
  321.     FreeMem((byte *)host_parms.membase-membase_offs,host_parms.memsize+3*32);
  322. #endif
  323.  
  324. //#ifndef __PPC__
  325. //  if (COM_CheckParm("-hack"))
  326. //  MMUHackOff();
  327. //#endif
  328.  
  329. #ifdef __STORM__
  330.   if (TimerBase) {
  331.     if (!CheckIO((struct IORequest *)timerio)) {
  332.       AbortIO((struct IORequest *)timerio);
  333.       WaitIO((struct IORequest *)timerio);
  334.     }
  335.     CloseDevice((struct IORequest *)timerio);
  336.     DeleteMsgPort(timerio->tr_node.io_Message.mn_ReplyPort);
  337.     DeleteIORequest(timerio);
  338.   }
  339. #else
  340. if (TimerBase) {
  341.   if (!CheckIO((struct IORequest *)timerio)) {
  342.     AbortIO((struct IORequest *)timerio);
  343.     WaitIO((struct IORequest *)timerio);
  344.   }
  345.   CloseDevice((struct IORequest *)timerio);
  346.   DeletePort(timerio->tr_node.io_Message.mn_ReplyPort);
  347.   DeleteExtIO((struct IORequest *)timerio);
  348. }
  349. #endif
  350.  
  351.  
  352. #if defined(__PPC__) && !defined(WOS)
  353.   /* cleanup GetSysTimePPC() emulation for PowerUp */
  354.   ExitSysTimePPC();
  355. #endif
  356.  
  357. #ifdef __PPC__
  358.   if (no68kFPU) {
  359.     if (MathIeeeDoubBasBase)
  360.       CloseLibrary(MathIeeeDoubBasBase);
  361.   }
  362. #endif
  363.  
  364.   if (LowLevelBase)
  365.     CloseLibrary(LowLevelBase);
  366.   if (UtilityBase)
  367.     CloseLibrary(UtilityBase);
  368.  
  369.   for (i=1; i<MAX_HANDLES; i++) {
  370.     if (sys_handles[i])
  371.       Close(sys_handles[i]);
  372.   }
  373.   exit(rc);
  374. }
  375.  
  376.  
  377. void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
  378. {
  379. }
  380.  
  381.  
  382. void Sys_DebugLog(char *file, char *fmt, ...)
  383. {
  384.   va_list argptr; 
  385.   static char data[1024];
  386.   BPTR fh;
  387.  
  388.   va_start(argptr, fmt);
  389.   vsprintf(data, fmt, argptr);
  390.   va_end(argptr);
  391.   if (fh = Open(file,MODE_READWRITE)) {
  392.     Seek(fh,0,OFFSET_END);
  393.     Write(fh,data,(LONG)strlen(data));
  394.     Close(fh);
  395.   }
  396. }
  397.  
  398. void Sys_Error (char *error, ...)
  399. {
  400.   va_list         argptr;
  401.  
  402.   printf ("I_Error: ");   
  403.   va_start (argptr,error);
  404.   vprintf (error,argptr);
  405.   va_end (argptr);
  406.   printf ("\n");
  407.  
  408.   if (cls.state == ca_connected) {
  409.     printf("disconnecting from server...\n");
  410.     CL_Disconnect ();   /* leave server gracefully (phx) */
  411.   }
  412.   cleanup(1);
  413. }
  414.  
  415. void Sys_Printf (char *fmt, ...)
  416. {
  417.   if (!nostdout) {
  418.     va_list         argptr;
  419.  
  420.     va_start (argptr,fmt);
  421.     vprintf (fmt,argptr);
  422.     va_end (argptr);
  423.   }
  424. }
  425.  
  426. void Sys_Quit (void)
  427. {
  428.   cleanup(0);
  429. }
  430.  
  431. double Sys_FloatTime (void)
  432. {
  433.   struct timeval tv;
  434.  
  435. #ifdef __PPC__
  436.   GetSysTimePPC(&tv);
  437. #else
  438.   GetSysTime(&tv);
  439. #endif
  440.   return ((double)(tv.tv_secs-FirstTime) + (((double)tv.tv_micro) / 1000000.0));
  441. }
  442.  
  443. char *Sys_ConsoleInput (void)
  444. {
  445.   if (coninput) {
  446.     static const char *backspace = "\b \b";
  447.     static char text[256];
  448.     static int len = 0;
  449.     char ch;
  450.  
  451.     while (WaitForChar(amiga_stdin,10) == DOSTRUE) {
  452.       Read(amiga_stdin,&ch,1);  /* note: console is in RAW mode! */
  453.       if (ch == '\r') {
  454.         ch = '\n';
  455.         Write(amiga_stdout,&ch,1);
  456.         text[len] = 0;
  457.         len = 0;
  458.         return text;
  459.       }
  460.       else if (ch == '\b') {
  461.         if (len > 0) {
  462.           len--;
  463.           Write(amiga_stdout,(char *)backspace,3);
  464.         }
  465.       }
  466.       else {
  467.         if (len < sizeof(text)-1) {
  468.           Write(amiga_stdout,&ch,1);
  469.           text[len++] = ch;
  470.         }
  471.       }
  472.     }
  473.   }
  474.   return NULL;
  475. }
  476.  
  477. void Sys_Sleep (void)
  478. {
  479. }
  480.  
  481. void Sys_HighFPPrecision (void)
  482. {
  483. }
  484.  
  485. void Sys_LowFPPrecision (void)
  486. {
  487. }
  488.  
  489.  
  490. //=============================================================================
  491.  
  492. main (int argc, char *argv[])
  493. {
  494.   struct timeval tv;
  495.   quakeparms_t parms;
  496.   double time, oldtime, newtime;
  497.   struct MsgPort *timerport;
  498.   char cwd[128];
  499.   struct GfxBase *GfxBase;
  500.   int i;
  501.  
  502.   memset(&parms,0,sizeof(parms));
  503.   parms.memsize = 16*1024*1024;  /* 16MB is default */
  504.  
  505.   /* parse command string */
  506.   COM_InitArgv (argc, argv);
  507.   parms.argc = com_argc;
  508.   parms.argv = com_argv;
  509.  
  510. //#ifndef __PPC__
  511. //  if (COM_CheckParm("-hack"))
  512. //  MMUHackOn();
  513. //#endif
  514.  
  515.   host_parms.membase = parms.cachedir = NULL;
  516.   if ((UtilityBase = OpenLibrary("utility.library",36)) == NULL ||
  517.       (LowLevelBase = OpenLibrary("lowlevel.library",36)) == NULL)
  518.     Sys_Error("OS2.0 required!");
  519. #ifdef __PPC__
  520.   no68kFPU = COM_CheckParm("-no68kfpu") != 0;
  521.   if (no68kFPU) {
  522.      if (!(MathIeeeDoubBasBase = OpenLibrary("mathieeedoubbas.library",36)))
  523.        Sys_Error("mathieeedoubbas.library is missing");
  524.   }
  525. #endif
  526.   amiga_stdin = Input();
  527.   amiga_stdout = Output();
  528.  
  529.   isDedicated = COM_CheckParm("-dedicated") != 0;
  530.   nostdout = ! (COM_CheckParm("-stdout"));   // modified: M.Tretene to avoid the >NIL: problem
  531.   coninput = COM_CheckParm("-console");
  532.   if (coninput)
  533.     SetMode(amiga_stdin,1);  /* put console into RAW mode */
  534.  
  535. #if defined(__PPC__) && !defined(WOS)
  536.   /* init GetSysTimePPC() emulation for PowerUp */
  537.   InitSysTimePPC();
  538. #endif
  539.  
  540.   /* open timer.device */
  541.  
  542. #ifdef __STORM__  
  543.   if (timerport = CreateMsgPort())
  544.   {
  545.    if (timerio = CreateIORequest(timerport,sizeof(struct timerequest)))
  546.    {
  547.     if (OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *)timerio,0) == 0)
  548.     {
  549.      TimerBase = (struct Library *)timerio->tr_node.io_Device;
  550.     }
  551.     else
  552.     {
  553.      DeleteIORequest(timerio);
  554.      DeleteMsgPort(timerport);
  555.     }
  556.    }
  557.    else DeleteMsgPort(timerport);
  558.   }
  559. #else
  560. if (timerport = CreatePort(NULL,0)) {
  561.   if (timerio = (struct timerequest *)
  562.                  CreateExtIO(timerport,sizeof(struct timerequest))) {
  563.     if (OpenDevice(TIMERNAME,UNIT_MICROHZ,
  564.                    (struct IORequest *)timerio,0) == 0) {
  565.       TimerBase = (struct Library *)timerio->tr_node.io_Device;
  566.     }
  567.     else {
  568.       DeleteExtIO((struct IORequest *)timerio);
  569.       DeletePort(timerport);
  570.     }
  571.   }
  572.   else
  573.     DeletePort(timerport);
  574. }
  575. #endif
  576.   
  577.   
  578.   if (!TimerBase)
  579.     Sys_Error("Can't open timer.device");
  580.   usleep(1);  /* don't delete, otherwise we can't do timer.device cleanup */
  581.  
  582. #ifdef __PPC__
  583.   GetSysTimePPC(&tv);
  584.   FirstTime = tv.tv_secs;
  585.   GetSysTime(&tv);
  586.   FirstTime2 = tv.tv_secs;
  587. #else
  588.   GetSysTime(&tv);
  589.   FirstTime2 = FirstTime = tv.tv_secs;
  590. #endif
  591.  
  592.   if (i = COM_CheckParm("-mem"))
  593.     parms.memsize = (int)(Q_atof(com_argv[i+1]) * 1024 * 1024);
  594.  
  595.   /* alloc 16-byte aligned quake memory */
  596.   parms.memsize = (parms.memsize+15)&~15;
  597.   
  598. #ifdef WOS  
  599.   if ((parms.membase = AllocVecPPC((ULONG)parms.memsize,MEMF_FAST,32)) == NULL)
  600.     Sys_Error("Can't allocate %ld bytes\n", parms.memsize);
  601. #else  
  602.   if ((parms.membase = AllocMem((ULONG)parms.memsize,MEMF_FAST)) == NULL)
  603.     Sys_Error("Can't allocate %ld bytes\n", parms.memsize);
  604.   if ((ULONG)parms.membase & 8)
  605.     membase_offs = 40;  /* guarantee 16-byte aligment */
  606.   else
  607.     membase_offs = 32;
  608.   parms.membase = (char *)parms.membase + membase_offs;
  609.   parms.memsize -= 3*32;
  610. #endif
  611.  
  612.   /* get name of current directory */
  613.   GetCurrentDirName(cwd,128);
  614.   parms.basedir = cwd;
  615.  
  616.   /* set the clock constant */
  617.   if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",36)) {
  618.     if (GfxBase->DisplayFlags & PAL)
  619.       sysclock = CLOCK_PAL;
  620.     else
  621.       sysclock = CLOCK_NTSC;
  622.     CloseLibrary((struct Library *)GfxBase);
  623.   }
  624.  
  625.   Host_Init (&parms);
  626.   oldtime = Sys_FloatTime () - 0.1;
  627.   while (1)
  628.   {
  629.     newtime = Sys_FloatTime ();
  630.     time = newtime - oldtime;
  631.     Host_Frame (time);
  632.  
  633.     oldtime = newtime;
  634.   }
  635. }
  636.