616b23d3c4c8d1c75b94e78f1c09d4580dbcce32
[eradicate] / src / sdl / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <limits.h>
5 #include <SDL/SDL.h>
6 #include "game.h"
7 #include "timer.h"
8
9 #define FB_WIDTH        640
10 #define FB_HEIGHT       480
11
12 static void handle_event(SDL_Event *ev);
13 static void toggle_fullscreen(void);
14
15 static int sdlkey_to_gamekey(int sdlkey, unsigned int mod);
16
17
18 static int quit;
19 static SDL_Surface *fbsurf;
20
21 static int fbscale = 1;
22 static int xsz, ysz;
23 static unsigned int sdl_flags = SDL_SWSURFACE;
24
25
26 int main(int argc, char **argv)
27 {
28         int s;
29         char *env;
30         void *fb_buf;
31
32         if((env = getenv("FBSCALE")) && (s = atoi(env))) {
33                 fbscale = s;
34                 printf("Framebuffer scaling x%d\n", fbscale);
35         }
36
37         xsz = FB_WIDTH * fbscale;
38         ysz = FB_HEIGHT * fbscale;
39         fb_width = xsz;
40         fb_height = ysz;
41
42         fb_size = FB_WIDTH * FB_HEIGHT * FB_BPP / 8;
43         if(!(fb_buf = malloc(fb_size + FB_WIDTH * 4))) {
44                 fprintf(stderr, "failed to allocate virtual framebuffer\n");
45                 return 1;
46         }
47         fb_pixels = (char*)fb_buf + FB_WIDTH * 2;
48
49         SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE);
50         if(!(fbsurf = SDL_SetVideoMode(xsz, ysz, FB_BPP, sdl_flags))) {
51                 fprintf(stderr, "failed to set video mode %dx%d %dbpp\n", FB_WIDTH, FB_HEIGHT, FB_BPP);
52                 free(fb_pixels);
53                 SDL_Quit();
54                 return 1;
55         }
56         SDL_WM_SetCaption("eradicate/SDL", 0);
57         SDL_ShowCursor(0);
58
59         time_msec = 0;
60         if(init(argc, argv) == -1) {
61                 free(fb_pixels);
62                 SDL_Quit();
63                 return 1;
64         }
65
66         reset_timer();
67
68         while(!quit) {
69                 SDL_Event ev;
70                 while(SDL_PollEvent(&ev)) {
71                         handle_event(&ev);
72                         if(quit) goto break_evloop;
73                 }
74
75                 time_msec = get_msec();
76                 draw();
77         }
78
79 break_evloop:
80         cleanup();
81         SDL_Quit();
82         return 0;
83 }
84
85 void game_quit(void)
86 {
87         quit = 1;
88 }
89
90 void wait_vsync(void)
91 {
92         unsigned long start = SDL_GetTicks();
93         unsigned long until = (start | 0xf) + 1;
94         while(SDL_GetTicks() <= until);
95 }
96
97 void blit_frame(void *pixels, int vsync)
98 {
99         int i, j;
100         unsigned short *sptr, *dptr;
101
102         if(vsync) {
103                 wait_vsync();
104         }
105
106         if(SDL_MUSTLOCK(fbsurf)) {
107                 SDL_LockSurface(fbsurf);
108         }
109
110         sptr = pixels;
111         dptr = (unsigned short*)fbsurf->pixels + (fbsurf->w - xsz) / 2;
112         for(i=0; i<FB_HEIGHT; i++) {
113                 for(j=0; j<FB_WIDTH; j++) {
114                         int x, y;
115                         unsigned short pixel = *sptr++;
116
117                         for(y=0; y<fbscale; y++) {
118                                 for(x=0; x<fbscale; x++) {
119                                         dptr[y * fbsurf->w + x] = pixel;
120                                 }
121                         }
122                         dptr += fbscale;
123                 }
124                 dptr += (fbsurf->w - FB_WIDTH) * fbscale;
125         }
126
127         if(SDL_MUSTLOCK(fbsurf)) {
128                 SDL_UnlockSurface(fbsurf);
129         }
130         SDL_Flip(fbsurf);
131 }
132
133 /*
134 static int bnmask(int sdlbn)
135 {
136         switch(sdlbn) {
137         case SDL_BUTTON_LEFT:
138                 return MOUSE_BN_LEFT;
139         case SDL_BUTTON_RIGHT:
140                 return MOUSE_BN_RIGHT;
141         case SDL_BUTTON_MIDDLE:
142                 return MOUSE_BN_MIDDLE;
143         default:
144                 break;
145         }
146         return 0;
147 }
148 */
149
150 static void handle_event(SDL_Event *ev)
151 {
152         int key;
153
154         switch(ev->type) {
155         case SDL_QUIT:
156                 quit = 1;
157                 break;
158
159         case SDL_KEYDOWN:
160         case SDL_KEYUP:
161                 if(ev->key.keysym.sym == SDLK_RETURN && (SDL_GetModState() & KMOD_ALT) &&
162                                 ev->key.state == SDL_PRESSED) {
163                         toggle_fullscreen();
164                         break;
165                 }
166                 if(key_event) {
167                         key = sdlkey_to_gamekey(ev->key.keysym.sym, ev->key.keysym.mod);
168                         key_event(key, ev->key.state == SDL_PRESSED ? 1 : 0);
169                 } else {
170                         if(ev->key.keysym.sym == SDLK_ESCAPE) {
171                                 quit = 1;
172                         }
173                 }
174                 break;
175
176                 /*
177         case SDL_MOUSEMOTION:
178                 mouse_x = ev->motion.x / fbscale;
179                 mouse_y = ev->motion.y / fbscale;
180                 break;
181
182         case SDL_MOUSEBUTTONDOWN:
183                 mouse_bmask |= bnmask(ev->button.button);
184                 if(0) {
185         case SDL_MOUSEBUTTONUP:
186                         mouse_bmask &= ~bnmask(ev->button.button);
187                 }
188                 mouse_x = ev->button.x / fbscale;
189                 mouse_y = ev->button.y / fbscale;
190                 break;
191                 */
192
193         default:
194                 break;
195         }
196 }
197
198 static void toggle_fullscreen(void)
199 {
200         SDL_Surface *newsurf;
201         unsigned int newflags = sdl_flags ^ SDL_FULLSCREEN;
202
203         if(!(newsurf = SDL_SetVideoMode(xsz, ysz, FB_BPP, newflags))) {
204                 fprintf(stderr, "failed to go %s\n", newflags & SDL_FULLSCREEN ? "fullscreen" : "windowed");
205                 return;
206         }
207
208         fbsurf = newsurf;
209         sdl_flags = newflags;
210 }
211
212 #define SSORG   '\''
213 #define SSEND   '`'
214 static char symshift[] = {
215         '"', 0, 0, 0, 0, '<', '_', '>', '?',
216         ')', '!', '@', '#', '$', '%', '^', '&', '*', '(',
217         0, ':', 0, '+', 0, 0, 0,
218         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
219         '{', '|', '}', 0, 0, '~'
220 };
221
222
223 static int sdlkey_to_gamekey(int sdlkey, unsigned int mod)
224 {
225         if(sdlkey < 128) {
226                 if(mod & (KMOD_SHIFT)) {
227                         if(sdlkey >= 'a' && sdlkey <= 'z') {
228                                 sdlkey = toupper(sdlkey);
229                         } else if(sdlkey >= SSORG && sdlkey <= SSEND) {
230                                 sdlkey = symshift[sdlkey - SSORG];
231                         }
232                 }
233                 return sdlkey;
234         }
235         if(sdlkey < 256) return 0;
236         return sdlkey - 128;
237 }