moving on
[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 = FB_WIDTH;
40         fb_height = FB_HEIGHT;
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         vmem = fb_pixels = (uint16_t*)((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(show_fps) dbg_fps(pixels);
103
104         if(vsync) {
105                 wait_vsync();
106         }
107
108         if(SDL_MUSTLOCK(fbsurf)) {
109                 SDL_LockSurface(fbsurf);
110         }
111
112         sptr = pixels;
113         dptr = (unsigned short*)fbsurf->pixels + (fbsurf->w - xsz) / 2;
114         for(i=0; i<FB_HEIGHT; i++) {
115                 for(j=0; j<FB_WIDTH; j++) {
116                         int x, y;
117                         unsigned short pixel = *sptr++;
118
119                         for(y=0; y<fbscale; y++) {
120                                 for(x=0; x<fbscale; x++) {
121                                         dptr[y * fbsurf->w + x] = pixel;
122                                 }
123                         }
124                         dptr += fbscale;
125                 }
126                 dptr += (fbsurf->w - FB_WIDTH) * fbscale;
127         }
128
129         if(SDL_MUSTLOCK(fbsurf)) {
130                 SDL_UnlockSurface(fbsurf);
131         }
132         SDL_Flip(fbsurf);
133 }
134
135 /*
136 static int bnmask(int sdlbn)
137 {
138         switch(sdlbn) {
139         case SDL_BUTTON_LEFT:
140                 return MOUSE_BN_LEFT;
141         case SDL_BUTTON_RIGHT:
142                 return MOUSE_BN_RIGHT;
143         case SDL_BUTTON_MIDDLE:
144                 return MOUSE_BN_MIDDLE;
145         default:
146                 break;
147         }
148         return 0;
149 }
150 */
151
152 static void handle_event(SDL_Event *ev)
153 {
154         int key;
155
156         switch(ev->type) {
157         case SDL_QUIT:
158                 quit = 1;
159                 break;
160
161         case SDL_KEYDOWN:
162         case SDL_KEYUP:
163                 if(ev->key.keysym.sym == SDLK_RETURN && (SDL_GetModState() & KMOD_ALT) &&
164                                 ev->key.state == SDL_PRESSED) {
165                         toggle_fullscreen();
166                         break;
167                 }
168                 if(key_event) {
169                         key = sdlkey_to_gamekey(ev->key.keysym.sym, ev->key.keysym.mod);
170                         key_event(key, ev->key.state == SDL_PRESSED ? 1 : 0);
171                 } else {
172                         if(ev->key.keysym.sym == SDLK_ESCAPE) {
173                                 quit = 1;
174                         }
175                 }
176                 break;
177
178                 /*
179         case SDL_MOUSEMOTION:
180                 mouse_x = ev->motion.x / fbscale;
181                 mouse_y = ev->motion.y / fbscale;
182                 break;
183
184         case SDL_MOUSEBUTTONDOWN:
185                 mouse_bmask |= bnmask(ev->button.button);
186                 if(0) {
187         case SDL_MOUSEBUTTONUP:
188                         mouse_bmask &= ~bnmask(ev->button.button);
189                 }
190                 mouse_x = ev->button.x / fbscale;
191                 mouse_y = ev->button.y / fbscale;
192                 break;
193                 */
194
195         default:
196                 break;
197         }
198 }
199
200 static void toggle_fullscreen(void)
201 {
202         SDL_Surface *newsurf;
203         unsigned int newflags = sdl_flags ^ SDL_FULLSCREEN;
204
205         if(!(newsurf = SDL_SetVideoMode(xsz, ysz, FB_BPP, newflags))) {
206                 fprintf(stderr, "failed to go %s\n", newflags & SDL_FULLSCREEN ? "fullscreen" : "windowed");
207                 return;
208         }
209
210         fbsurf = newsurf;
211         sdl_flags = newflags;
212 }
213
214 #define SSORG   '\''
215 #define SSEND   '`'
216 static char symshift[] = {
217         '"', 0, 0, 0, 0, '<', '_', '>', '?',
218         ')', '!', '@', '#', '$', '%', '^', '&', '*', '(',
219         0, ':', 0, '+', 0, 0, 0,
220         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,
221         '{', '|', '}', 0, 0, '~'
222 };
223
224
225 static int sdlkey_to_gamekey(int sdlkey, unsigned int mod)
226 {
227         if(sdlkey < 128) {
228                 if(mod & (KMOD_SHIFT)) {
229                         if(sdlkey >= 'a' && sdlkey <= 'z') {
230                                 sdlkey = toupper(sdlkey);
231                         } else if(sdlkey >= SSORG && sdlkey <= SSEND) {
232                                 sdlkey = symshift[sdlkey - SSORG];
233                         }
234                 }
235                 return sdlkey;
236         }
237         if(sdlkey < 256) return 0;
238         return sdlkey - 128;
239 }