2 * Netris -- A free networked version of T*tris
3 * Copyright (C) 1994,1995,1996 Mark H. Weaver <mhw@netris.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <sys/types.h>
33 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event);
34 static EventGenRec alarmGen = {
35 &alarmGen, 0, FT_read, -1, AlarmGenFunc, EM_alarm
37 static EventGenRec *nextGen = &alarmGen;
39 static int myRandSeed = 1;
41 static long baseTimeval;
44 void AtExit(void (*handler)(void))
47 on_exit((void *)handler, NULL);
53 ///////////// HELP MESSAGES /////////////
58 "NETRIS %s\t(c) 1994-1996,1999 Mark H. Weaver <mhw@netris.org>\n"
59 " \t(c) 2002 Shiar <shiar@shiar.org>\n\n",
67 "This program is free software; you can redistribute it and/or modify\n"
68 "it under the terms of the GNU General Public License as published by\n"
69 "the Free Software Foundation; either version 2 of the License, or\n"
70 "(at your option) any later version.\n"
72 "This program is distributed in the hope that it will be useful,\n"
73 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
74 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
75 "GNU General Public License for more details.\n"
77 "You should have received a copy of the GNU General Public License\n"
78 "along with this program; if not, write to the Free Software\n"
79 "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
84 ///////////// RANDOM /////////////
87 * My really crappy random number generator follows
88 * Should be more than sufficient for our purposes though
90 void SRandom(int seed)
93 myRandSeed = seed % 31751 + 1;
96 int Random(int min, int max1)
97 { //return a random value
98 myRandSeed = (myRandSeed * 31751 + 15437) % 32767;
99 return myRandSeed % (max1 - min) + min;
102 ///////////// I/O /////////////
104 int MyRead(int fd, void *data, int len)
110 result = read(fd, data, left);
112 data = ((char *)data) + result;
115 else if (errno != EINTR)
121 int MyWrite(int fd, void *data, int len)
127 result = write(fd, data, left);
129 data = ((char *)data) + result;
132 else if (errno != EINTR)
138 ///////////// CONFIG /////////////
144 file_out = fopen(CONFIG_FILE, "w");
145 if (file_out == NULL) {
146 perror("Error writing config file");
150 fprintf(file_out, "### NETRIS %s Config file ###\n\n", version_string);
153 fprintf(stderr, "Wrote new game configuration to %s\n", CONFIG_FILE);
156 ///////////// TIME /////////////
158 void NormalizeTime(struct timeval *tv)
160 tv->tv_sec += tv->tv_usec / 1000000;
161 tv->tv_usec %= 1000000;
162 if (tv->tv_usec < 0) {
163 tv->tv_usec += 1000000;
168 void CatchAlarm(int sig)
171 signal(SIGALRM, CatchAlarm);
174 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event)
179 void SetTimeval(struct timeval *tv, long usec)
181 tv->tv_sec = usec / 1000000;
182 tv->tv_usec = usec % 1000000;
185 long GetTimeval(struct timeval *tv)
187 return tv->tv_sec * 1000000 + tv->tv_usec;
190 long AbsTimeval(void)
194 gettimeofday(&tv, NULL);
195 return GetTimeval(&tv);
198 void ResetBaseTime(void)
200 baseTimeval = AbsTimeval();
205 baseTimeval -= AbsTimeval();
208 void ResumeTime(void)
210 baseTimeval += AbsTimeval();
213 long CurTimeval(void)
215 return AbsTimeval() - baseTimeval;
218 static long SetITimer1(long interval, long value)
220 struct itimerval it, old;
222 SetTimeval(&it.it_interval, interval);
223 SetTimeval(&it.it_value, value);
224 if (setitimer(ITIMER_REAL, &it, &old) < 0)
226 signal(SIGALRM, CatchAlarm);
227 return GetTimeval(&old.it_value);
230 long SetITimer(long interval, long value)
234 old = SetITimer1(0, 0);
236 SetITimer1(interval, value);
240 ///////////// ... /////////////
242 volatile void die(char *msg)
248 volatile void fatal(char *msg)
250 fprintf(stderr, "%s\n", msg);
254 void BlockSignals(MySigSet *saved, ...)
260 va_start(args, saved);
261 #ifdef HAS_SIGPROCMASK
266 while ((sig = va_arg(args, int))) {
267 #ifdef HAS_SIGPROCMASK
268 sigaddset(&set, sig);
273 #ifdef HAS_SIGPROCMASK
274 sigprocmask(SIG_BLOCK, &set, saved);
276 *saved = sigblock(set);
281 void RestoreSignals(MySigSet *saved, MySigSet *set)
283 #ifdef HAS_SIGPROCMASK
284 sigprocmask(SIG_SETMASK, set, saved);
287 *saved = sigsetmask(*set);
293 ///////////// EVENTS /////////////
295 void AddEventGen(EventGenRec *gen)
297 assert(gen->next == NULL);
298 gen->next = nextGen->next;
302 void RemoveEventGen(EventGenRec *gen)
304 // assert(gen->next != NULL); /* Be more forgiving, for SIGINTs */
306 while (nextGen->next != gen)
307 nextGen = nextGen->next;
308 nextGen->next = gen->next;
313 MyEventType WaitMyEvent(MyEvent *event, int mask)
318 int result, anyReady, anySet;
322 for (i = 0; i < FT_len; ++i)
324 anyReady = anySet = 0;
327 if (gen->mask & mask) {
331 FD_SET(gen->fd, &fds[gen->fdType]);
336 } while (gen != nextGen);
339 tv.tv_usec = (retry && !anyReady) ? 500000 : 0;
340 result = select(FD_SETSIZE, &fds[FT_read], &fds[FT_write],
341 &fds[FT_except], anyReady ? &tv : NULL);
344 if (retry && !anyReady)
350 if ((gen->mask & mask) && (gen->ready || (
351 result > 0 && gen->fd >= 0
352 && FD_ISSET(gen->fd, &fds[gen->fdType])
355 event->type = gen->func(gen, event);
356 if (event->type != E_none) {
362 } while (gen != nextGen);