dc240fd9a5a4dfa99cb663389654ff872c212803
[ansitris] / src / main.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <termios.h>
7 #include <sys/stat.h>
8 #include <sys/select.h>
9 #include <sys/time.h>
10 #include "game.h"
11
12 int init(void);
13 void cleanup(void);
14 long get_msec(void);
15
16 static const char *termfile = "/dev/tty";
17 static struct termios saved_term;
18 static struct timeval tv0;
19
20 int main(int argc, char **argv)
21 {
22         int res, c;
23         long msec, next;
24         struct timeval tv;
25
26         if(argc > 1) {
27                 termfile = argv[1];
28         }
29
30         if(init() == -1) {
31                 return 1;
32         }
33
34         gettimeofday(&tv0, 0);
35
36         tv.tv_sec = tick_interval / 1000;
37         tv.tv_usec = (tick_interval % 1000) * 1000;
38
39         for(;;) {
40                 fd_set rdset;
41                 FD_ZERO(&rdset);
42                 FD_SET(0, &rdset);
43
44                 while((res = select(1, &rdset, 0, 0, &tv)) == -1 && errno == EINTR);
45
46                 if(res > 0 && FD_ISSET(0, &rdset)) {
47                         while((c = fgetc(stdin)) >= 0) {
48                                 game_input(c);
49                                 if(quit) goto end;
50                         }
51                 }
52
53                 msec = get_msec();
54                 next = update(msec);
55
56                 tv.tv_sec = next / 1000;
57                 tv.tv_usec = (next % 1000) * 1000;
58         }
59
60 end:
61         cleanup();
62         return 0;
63 }
64
65 int init(void)
66 {
67         int fd;
68         struct termios term;
69
70         if((fd = open(termfile, O_RDWR | O_NONBLOCK)) == -1) {
71                 fprintf(stderr, "failed to open terminal device: %s: %s\n", termfile, strerror(errno));
72                 return -1;
73         }
74
75         if(tcgetattr(fd, &term) == -1) {
76                 fprintf(stderr, "failed to get terminal attributes: %s\n", strerror(errno));
77                 return -1;
78         }
79         saved_term = term;
80         term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
81         term.c_oflag &= ~OPOST;
82         term.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
83         term.c_cflag = (term.c_cflag & ~(CSIZE | PARENB)) | CS8;
84
85         if(tcsetattr(fd, TCSAFLUSH, &term) == -1) {
86                 fprintf(stderr, "failed to change terminal attributes: %s\n", strerror(errno));
87                 return -1;
88         }
89
90         close(0);
91         close(1);
92         close(2);
93         dup(fd);
94         dup(fd);
95
96         umask(002);
97         open("ansitris.log", O_WRONLY | O_CREAT, 0664);
98
99
100         if(init_game() == -1) {
101                 return -1;
102         }
103
104         return 0;
105 }
106
107 void cleanup(void)
108 {
109         cleanup_game();
110         tcsetattr(0, TCSAFLUSH, &saved_term);
111 }
112
113 long get_msec(void)
114 {
115         struct timeval tv;
116
117         gettimeofday(&tv, 0);
118
119         return (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
120 }