File: globals.c

package info (click to toggle)
rockdodger 1.1.3-2
  • links: PTS
  • area: main
  • in suites: buster
  • size: 2,428 kB
  • sloc: ansic: 5,871; makefile: 159; sh: 21
file content (331 lines) | stat: -rw-r--r-- 11,821 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
#include "globals.h"
#include <assert.h>
#include <math.h>
#include "display_subsystem.h"
#include "game_state.h"
#include "highscore_io.h"
#include "input_functions.h"
#include "SFont.h"
#include "scroller.h"
#include "ship.h"
#include "sound.h"

struct Setup_Data {
  Scroller_t *scroller;
  short current;
  const char *entry_name;
  const char *description; //!< will be in the scroller on the bottom of the screen
  char *values[12];
};

char *edition_name;
int xsize = 800;
int ysize = 600;
SDL_Surface *surf_screen = NULL;
SDL_Surface *surf_green_block = NULL;
SDL_Surface *surf_t_rock = NULL;	// Title element "rock"
SDL_Surface *surf_t_dodger = NULL;	// Title element "dodgers"
spacedots_t *current_spacedot_engine = NULL;
unsigned short opt_fullscreen = 1;
unsigned short opt_cicada_spacedots = 0;
unsigned short opt_intro = 2;
float movementrate;
float level = 0;
float shieldlevel, laserlevel, shieldpulse = 0;
int initialshield, gameover = 0;

RD_VIDEO_TYPE heatcolor[W * 3];

enum states state = TITLE_PAGE;	//!< current game state
float state_timeout = 600.0;	//!< timeout before next game state switch
float fadetimer = 0;
Uint32 initticks = 0;
Uint32 last_ticks = 0;
Uint32 ticks_since_last = 0;
Uint32 ign_k_utl_ticks = 0;
int music_volume = 128; //See sound.c...
int nships;
int last_levelup_snd;
uiff_ctx_t *iff_ctx;

static const char resolution_format[] = "resolution = ( %d, %d )\n";
static const char spacedots_format[] = "spacedots = %31s\n";
static const char fullscreen_format[] = "fullscreen = %31s\n";
static const char intro_format[] = "intro = %31s\n";
static const char version_format[] = "version = %13s\n";
static const char music_volume_format[] = "musvol = %13s\n";
static char configuration_file_version[14];

struct Setup_Data setup[] = {
  { NULL, 0, "", "Use cursor keys to select and change options, press enter or F1 to quit the screen.", { "", NULL } },
  { NULL, 0, "resolution", "Select the screen resolution!", { "", "640x480", "800x480", "800x600", "1024x768", "1152x864", "1280x1024", "1440x900", "1600x900", NULL } },
  { NULL, 0, "fullscreen", "Use the full-screen display or windowed mode for rockdodger?", { "fullscreen", "windowed", NULL } },
  { NULL, 0, "spacedots", "How are the spacedots (the little stars in the background) drawn? The classic version draws them directly into the surface, the cicada version uses surfaces (may be faster).", { "classic", "cicada", NULL } },
  { NULL, 8, "music volume", "Set the volume for the background music.", { "0", "16", "32", "48", "64", "80", "96", "112", "128", "144", "160" } },
  { NULL, 0, "intro", "Should the intro be displayed? The intro is usually only displayed for the first time after a version change.", { "no", "yes", NULL } },
  { NULL, 0, "", "Rockdoger V"VERSION" compiled on "COMPILEDATE".", { "", NULL } },
  { NULL, 0, "activate config?", "Set this to yes and press ENTER to activate the current configuration. Valid options are: 'no' keep old configuration, 'yes' activate configuration, 'yes and save' activate and save the configuration.", { "no", "yes", "yes and save", NULL } },
  { NULL, 0, NULL }
};
#define SETUP_SIZE (sizeof(setup) / sizeof(struct Setup_Data))

void update_movement_rate() {
  ticks_since_last = SDL_GetTicks() - last_ticks;
  last_ticks = SDL_GetTicks();
  if(ticks_since_last > 200) {
    movementrate = 0;
  } else {
    movementrate = ticks_since_last / 50.0;
  }
}


void cleanup_globals() {
  struct Setup_Data *setupptr;

  initticks = SDL_GetTicks();
  for(setupptr = setup; setupptr->entry_name; ++setupptr) {
    if(setupptr->scroller) {
      destroy_scroller(setupptr->scroller);
      setupptr->scroller = NULL;
    }
  }
}


struct Setup_Data *find_setup_entry(const char *name) {
  struct Setup_Data *setupptr;
  
  for(setupptr = setup; setupptr->entry_name; ++setupptr) {
    if(strcmp(name, setupptr->entry_name) == 0) return setupptr;
  }
  return NULL;
}

void save_setup() {
  FILE *f;
  char buf[256];
  struct Setup_Data *setupptr;

  snprintf(buf, sizeof(buf) - 1, "%s/.rockdodger", getenv("HOME"));
  if((f = fopen(buf, "w")) == NULL) return;
#ifdef DEBUG
  fprintf(stderr, "Writing config to '%s'.\n", buf);
#endif
  fprintf(f, "#rockdodger configuration\n");
  fprintf(f, version_format, VERSION);
  fprintf(f, resolution_format, xsize, ysize);
  //
  setupptr = find_setup_entry("spacedots");
  assert(setupptr);
  fprintf(f, spacedots_format, setupptr->values[setupptr->current]);
  //
  setupptr = find_setup_entry("fullscreen");
  assert(setupptr);
  fprintf(f, fullscreen_format, setupptr->values[setupptr->current]);
  //
  setupptr = find_setup_entry("intro");
  assert(setupptr);
  fprintf(f, intro_format, setupptr->values[setupptr->current]);
  //
  setupptr = find_setup_entry("music volume");
  assert(setupptr);
  fprintf(f, music_volume_format, setupptr->values[setupptr->current]);
  fclose(f);
}


int load_setup() {
  FILE *f;
  char buf[256];
  char inpbuf[32];
  int x0, x1;

  snprintf(buf, sizeof(buf) - 1, "%s/.rockdodger", getenv("HOME"));
  if(!(f = fopen(buf, "r"))) return 0;
  while(fgets(buf, sizeof(buf), f) != NULL) {
    if(strlen(buf) == 0 || buf[0] == '#') continue;
    if(sscanf(buf, resolution_format, &x0, &x1) == 2) {
      if(x0 > 0 && x1 > 0) {
	xsize = x0;
	ysize = x1;
      }
    } else if(sscanf(buf, spacedots_format, inpbuf) == 1) {
      if(strcmp(inpbuf, "cicada") == 0)
	opt_cicada_spacedots = 1;
      else
	opt_cicada_spacedots = 0;
    } else if(sscanf(buf, fullscreen_format, inpbuf) == 1) {
      if(strcmp(inpbuf, "fullscreen") == 0)
	opt_fullscreen = 1;
      else
	opt_fullscreen = 0;	
    } else if(sscanf(buf, intro_format, inpbuf) == 1) {
      if(opt_intro != 3) opt_intro = (strcmp(inpbuf, "yes") == 0) ? 1 : 0;
    } else if(sscanf(buf, version_format, configuration_file_version) == 1) {
      if(strcmp(configuration_file_version, VERSION) != 0) opt_intro = 3;
    } else if(sscanf(buf, music_volume_format, inpbuf) == 1) {
      music_volume = atoi(inpbuf);
      //Check for illegal values. Oh boy, I am sooo lazy.
      if(music_volume < 0) music_volume = 0;
      else if(music_volume > 160) music_volume = 160;
    } else {
      printf("Unknown setup line '%s'.\n", buf);
    }
  }
  fclose(f);
  return 1;
}


void setuploop() {
  int i;
  short old_config[SETUP_SIZE];
  inputstate_t inputstate;
  char txtbuf[181];
  int crsrpos = 0;
  struct Setup_Data *setupptr;
  char resolution_buf[10];
  short activate_config;
  SDL_Rect drect = { 16, 0, 0, 0 };
  SDL_Rect srect = { 0, 0, surf_screen->w - 32, 20 };

  play_tune(4);
  for(i = 0; i < SETUP_SIZE; ++i) old_config[i] = setup[i].current;
  state_timeout = 69105;
  setupptr = find_setup_entry("music volume");
  assert(setupptr);
  setupptr->current = music_volume >> 4;
  assert(setupptr->current < 11);
  setupptr = find_setup_entry("fullscreen");
  assert(setupptr);
  setupptr->current = opt_fullscreen == 0 ? 1 : 0;
  setupptr = find_setup_entry("intro");
  assert(setupptr);
  setupptr->current = opt_intro == 1 ? 1 : 0;
  setupptr = find_setup_entry("spacedots");
  assert(setupptr);
  setupptr->current = opt_cicada_spacedots;
  setupptr = find_setup_entry("resolution");
  assert(setupptr);
  sprintf(resolution_buf, "%dx%d", xsize, ysize);
  setupptr->values[0] = resolution_buf;
  while(state == SETUP) {
    update_movement_rate();
    (void) input_subsystem(&inputstate);
    /* TODO: really not possible in setup? */
    handle_state_timeout(0);
    if(inputstate.inputstate[UP]) {
      --crsrpos;
      temporary_disable_key_input();
    } else if(inputstate.inputstate[DOWN]) {
      ++crsrpos;
      temporary_disable_key_input();
    } else if(inputstate.inputstate[RIGHT]) {
      setupptr = setup + crsrpos;
      if(setupptr->values[++setupptr->current] == NULL) setupptr->current = 0;
      temporary_disable_key_input();
    } else if(inputstate.inputstate[LEFT]) {
      setupptr = setup + crsrpos;
      if(--setupptr->current < 0) {
	while(setupptr->values[++setupptr->current]); //This will find the null pointer.
	--setupptr->current; //Now last entry.
      }
      temporary_disable_key_input();
    } else if(inputstate.inputstate[INPUT_SELECT]) {
      state = TITLE_PAGE;
    }
    /*
     * If the cursor positon is less then zero set it to zero or if
     * the position would be pointing to NULL which is the end of
     * available options also ignore the keystroke. If the first
     * character is less then a space then ignore it, too. We will use
     * control characters for special use cases...
     */
    if(crsrpos < 0) crsrpos = 0;
    else if(setup[crsrpos].entry_name == NULL || (setup[crsrpos].entry_name[0] < ' ' && setup[crsrpos].entry_name[0] != 0)) --crsrpos;
    if(setup[crsrpos].scroller == NULL) {
      setup[crsrpos].scroller = init_scroller(setup[crsrpos].description, surf_screen->h - 30, 4.62384, surf_screen->w);
    }
    //display subsystem
    draw_background_objects();
    XCenteredString(surf_screen, 20, "SETUP");
    for(setupptr = setup, i = 0; setupptr->entry_name; ++setupptr, ++i) {
      sprintf(txtbuf, "%-70s %12s", setupptr->entry_name, setupptr->values[setupptr->current]);
      PutString(surf_screen, 20, 60 + i * 22, setupptr->entry_name);
      PutString(surf_screen, surf_screen->w - 20 - SFont_wide(setupptr->values[setupptr->current]), 60 + i * 22, setupptr->values[setupptr->current]);
      SDL_SetAlpha(surf_green_block, SDL_SRCALPHA, (int) (51.0 + 30.0 * sinf(fadetimer)));
      drect.y = 60 + crsrpos * 22;
      SDL_BlitSurface(surf_green_block, &srect, surf_screen, &drect);
    }
    assert(setup[crsrpos].scroller);
    if(setup[crsrpos].scroller) update_and_draw_scroller(setup[crsrpos].scroller, surf_screen, movementrate);
    // Update the surface
    SDL_Flip(surf_screen);
    fadetimer += movementrate / 8.2;
  }
  //We are leaving... check if activated
  setupptr = find_setup_entry("activate config?");
  assert(setupptr);
  activate_config = setupptr->current;
  assert(activate_config >= 0 && activate_config <= 2);
  if(activate_config > 0) {
    setupptr->current = 0;
    //Activate
    setupptr = find_setup_entry("resolution");
    assert(setupptr);
    if(setupptr->current > 0) {
      i = sscanf(setupptr->values[setupptr->current], "%dx%d", &xsize, &ysize);
      assert(i == 2);
    }
    setupptr = find_setup_entry("fullscreen");
    assert(setupptr);
    opt_fullscreen = setupptr->current == 0 ? 1 : 0; //0=fullscreen, 1=no fullscrenn, qed.
    setupptr = find_setup_entry("spacedots");
    assert(setupptr);
    opt_cicada_spacedots = setupptr->current;
    setupptr = find_setup_entry("music volume");
    assert(setupptr);
    music_volume = atoi(setupptr->values[setupptr->current]);
    state = RESTART_GAME;
  }
  if(activate_config == 2) {
    save_setup();
  }
  if(activate_config == 0)
    for(i = 0; i < SETUP_SIZE; ++i) setup[i].current = old_config[i];
  play_tune(0);
  state_timeout = 496.69105;
}

uiff_ctx_t *get_iff_rock(const char *fname) {
  FILE *f = NULL;
  uiff_ctx_t *ctx = NULL;

  printf("Rockdodger data file is '%s'.\n", fname);
  if(!(f = fopen(fname, "r"))) {
    perror("Can not open rockdodger data-file");
  } else if((ctx = uiff_from_file(f, FORM, MakeID('R', 'O', 'C', 'K'))) == NULL) {
    perror("No context");
    fclose(f); 
  }
  return ctx;
}

char *load_edition_name(uiff_ctx_t iff) {
  int32_t chunksize;
  char buf[33];
  size_t bread;

  uiff_rewind_group(&iff);
  chunksize = uiff_find_chunk_ctx(&iff, MakeID('E', 'D', 'T', 'N'));
  assert(printf("FORM.ROCK EDTN size = %d\n", (int)chunksize));
  if(chunksize < 0) {
    edition_name = strcpy(buf, "#UNKNOWN#");
  } else {
    bread = fread(buf, 1, chunksize < sizeof(buf) - 1 ? chunksize : sizeof(buf) - 1, iff.f);
    assert(bread < sizeof(buf) - 1);
    buf[bread] = 0;
  }
  return strdup(buf);
}