rendered paste body
/*
*
* main.c
* Created on the 23rd of August 2005
*
* Part of the OpenJazz project
*
*
* Copyright (c) 2005 Alister Thomson
* MacOSX code by Mark Spear (Ice M A N)
* Dreamcast code by Troy(GPF)
* GP2X code by Israel LÛpez Fern·ndez (Puck2099)
* GP32 code by A600
*
* OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Contains the main function and core utility functions.
*
*/
// Uncomment the following line to compile on the GP2X
//#define macosx
#define Extern
#include "OpenJazz.h"
#include <string.h>
#include <stdio.h>
#ifdef _arch_dreamcast
#include <SDL_dreamcast.h>
#include <kos.h>
#include <arch/gdb.h>
#endif
#ifdef __GP2X__
#include "minimal.h"
#endif
#ifdef GP32
#include <x_gp32.h>
#endif
#include <SDL/SDL.h>
// Functions in font.c
extern font * loadFont (char * fn);
extern void freeFont (font * f);
// Functions in sound.c
extern int loadSounds (char * fn);
extern void freeSounds (void);
int oldTicks;
int fakePalette;
FILE * fopenFromPath (char * fileName) {
FILE *f;
char *filePath;
// Allocate space for the file path
filePath = malloc(strlen(path) + strlen(fileName) + 1);
// Create the file path
strcpy(filePath, path);
strcat(filePath, fileName);
printf("Opening %s\n", filePath);
// Open the file
f = fopen(filePath, "rb");
// Free the file path
free(filePath);
return f;
}
int fileExists (char * fileName) {
FILE *f;
printf("Check: ");
f = fopenFromPath(fileName);
if (f == NULL) return 0;
fclose(f);
return 1;
}
unsigned char * loadRLE (FILE *f, int length) {
char *buffer;
int rle, pos, byte, count, next;
// Determine the byte that follows the block
next = fgetc(f);
next += fgetc(f) << 8;
next += ftell(f);
// Allocate memory for the decompressed data
buffer = malloc(length);
pos = 0;
while (pos < length) {
rle = fgetc(f);
if (rle > 127) {
byte = fgetc(f);
for (count = 0; count < (rle & 127); count++) {
buffer[pos++] = byte;
if (pos >= length) break;
}
} else if (rle > 0) {
for (count = 0; count < rle; count++) {
buffer[pos++] = fgetc(f);
if (pos >= length) break;
}
} else break;
}
fseek(f, next, SEEK_SET);
return buffer;
}
void skipRLE (FILE *f) {
int next;
next = fgetc(f);
next += fgetc(f) << 8;
fseek(f, next, SEEK_CUR);
return;
}
char * loadString (FILE *f) {
char *string;
int length, count;
length = fgetc(f);
if (length) {
string = malloc(length + 1);
for (count = 0; count < length; count++) string[count] = fgetc(f);
string[length] = 0;
} else {
// If the length is not given, assume it is an 8.3 (or 7.3, etc) file name
string = malloc(13);
for (count = 0; (count < 8) && (!length); count++) {
string[count] = fgetc(f);
if (string[count] == '.') length = ~0;
}
string[count++] = fgetc(f);
string[count++] = fgetc(f);
string[count++] = fgetc(f);
string[count] = 0;
}
return string;
}
SDL_Surface * createSurface (unsigned char * pixels, int width, int height) {
SDL_Surface *ret;
int y;
// Create the surface
ret = SDL_CreateRGBSurface(SDL_HWSURFACE, width, height, 8, 0, 0, 0, 0);
// Set the surface's palette
SDL_SetPalette(ret, SDL_LOGPAL, logicalPalette, 0, 256);
// Upload pixel data to the surface
if (SDL_MUSTLOCK(ret)) SDL_LockSurface(ret);
for (y = 0; y < height; y++)
memcpy(ret->pixels + (ret->pitch * y), pixels + (width * y), width);
if (SDL_MUSTLOCK(ret)) SDL_UnlockSurface(ret);
// Free redundant pixel data
free(pixels);
return ret;
}
SDL_Surface * createBlankSurface (void) {
SDL_Surface *ret;
unsigned char *pixels;
pixels = malloc(1);
*pixels = 0;
ret = createSurface(pixels, 1, 1);
SDL_SetColorKey(ret, SDL_SRCCOLORKEY, 0);
return ret;
}
void loadPalette (SDL_Color *palette, FILE *f) {
unsigned char *buffer;
int count;
buffer = loadRLE(f, 768);
// printf("JASC-PAL\n0100\n256\n");
for (count = 0; count < 256; count++) {
// Palette entries are 6-bit
// Shift them upwards to 8-bit, and fill in the lower 2 bits
palette[count].r = (buffer[count * 3] << 2) + (buffer[count * 3] >> 4);
palette[count].g = (buffer[(count * 3) + 1] << 2) +
(buffer[(count * 3) + 1] >> 4);
palette[count].b = (buffer[(count * 3) + 2] << 2) +
(buffer[(count * 3) + 2] >> 4);
// printf("%i %i %i\n", palette[count].r, palette[count].g,
// palette[count].b);
}
free(buffer);
return;
}
int loadMain (void) {
FILE *f;
unsigned char *pixels, *sorted;
int rle, pos, index, count, x, y;
// Generate the logical palette
for (count = 0; count < 256; count++) {
logicalPalette[count].r = count;
logicalPalette[count].g = count;
logicalPalette[count].b = count;
}
SDL_SetPalette(screen, SDL_LOGPAL, logicalPalette, 0, 256);
// Default level & difficulty settings
currentLevel = malloc(11);
strcpy(currentLevel, "level0.000");
nextLevel = malloc(11);
strcpy(nextLevel, "level0.000");
difficulty = 1;
// Load the panel
f = fopenFromPath("panel.000");
if (f == NULL) {
free(currentLevel);
free(nextLevel);
return FAILURE;
}
// Load the panel background
panel = loadSurface(f, 320, 32);
// Load the large panel font
// Starts at 4691 and goes 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-:.
pixels = malloc(320 * 8);
pixels[0] = 31;
pos = 1;
fseek(f, 4691, SEEK_SET);
// RLE decompression and horizontal to vertical character rearrangement
while (pos < 320 * 8) {
rle = fgetc(f);
if (rle >= 128) {
index = fgetc(f);
for (count = 0; count < (rle & 127); count++) {
pixels[(pos & 7) + ((pos / 320) * 8) + (((pos % 320)>>3) * 8 * 8)] =
index;
pos++;
}
} else if (rle > 0) {
for (count = 0; count < rle; count++) {
pixels[(pos & 7) + ((pos / 320) * 8) + (((pos % 320)>>3) * 8 * 8)] =
fgetc(f);
pos++;
}
} else break;
}
// Create ASCII->font map
for (count = 0; count < 45; count++) panelBigFont.map[count] = 39;
panelBigFont.map[45] = 36;
panelBigFont.map[46] = 38;
for (count = 47; count < 48; count++) panelBigFont.map[count] = 39;
for (; count < 58; count++) panelBigFont.map[count] = count - 48;
panelBigFont.map[58] = 37;
for (count = 59; count < 65; count++) panelBigFont.map[count] = 39;
for (; count < 91; count++) panelBigFont.map[count] = count - 55;
for (; count < 97; count++) panelBigFont.map[count] = 39;
for (; count < 123; count++) panelBigFont.map[count] = count - 87;
for (; count < 128; count++) panelBigFont.map[count] = 39;
// Set font dimensions
panelBigFont.w = malloc(40);
for (count = 0; count < 40; count++) panelBigFont.w[count] = 8;
panelBigFont.h = 8;
panelBigFont.pixels = createSurface(pixels, 8, 320);
// Load the small panel font
// Starts at 6975 and goes 0123456789oo (where oo = infinity)
pixels = malloc(320 * 7);
pos = 0;
fseek(f, 6975, SEEK_SET);
// RLE decompression and horizontal to vertical character rearrangement
while (pos < 320 * 7) {
rle = fgetc(f);
if (rle >= 128) {
index = fgetc(f);
for (count = 0; count < (rle & 127); count++) {
pixels[(pos & 7) + ((pos / 320) * 8) + (((pos % 320)>>3) * 8 * 7)] =
index;
pos++;
}
} else if (rle > 0) {
for (count = 0; count < rle; count++) {
pixels[(pos & 7) + ((pos / 320) * 8) + (((pos % 320)>>3) * 8 * 7)] =
fgetc(f);
pos++;
}
} else break;
}
// Create ASCII->font map
for (count = 0; count < 48; count++) panelSmallFont.map[count] = 12;
// Use :; to represent oo
for (; count < 60; count++) panelSmallFont.map[count] = count - 48;
for (; count < 128; count++) panelSmallFont.map[count] = 12;
// Set font dimensions
panelSmallFont.w = malloc(13);
for (count = 0; count < 13; count++) panelSmallFont.w[count] = 8;
panelSmallFont.h = 7;
panelSmallFont.pixels = createSurface(pixels, 8, 280);
// Load the panel's ammo graphics
fseek(f, 7537, SEEK_SET);
sorted = malloc(64 * 27);
pixels = loadRLE(f, 64 * 27);
for (y = 0; y < 27; y++) {
for (x = 0; x < 64; x++)
sorted[(y * 64) + x] = pixels[(y * 64) + (x >> 2) + ((x & 3) << 4)];
}
panelAmmo[0] = createSurface(sorted, 64, 27);
sorted = pixels; // Re-use the allocated memory
fseek(f, 8264, SEEK_SET);
pixels = loadRLE(f, 64 * 27);
for (y = 0; y < 27; y++) {
for (x = 0; x < 64; x++)
sorted[(y * 64) + x] = pixels[(y * 64) + (x >> 2) + ((x & 3) << 4)];
}
panelAmmo[1] = createSurface(sorted, 64, 27);
sorted = pixels; // Re-use the allocated memory
fseek(f, 9550, SEEK_SET);
pixels = loadRLE(f, 64 * 27);
for (y = 0; y < 27; y++) {
for (x = 0; x < 64; x++)
sorted[(y * 64) + x] = pixels[(y * 64) + (x >> 2) + ((x & 3) << 4)];
}
panelAmmo[2] = createSurface(sorted, 64, 27);
sorted = pixels; // Re-use the allocated memory
fseek(f, 11060, SEEK_SET);
pixels = loadRLE(f, 64 * 27);
for (y = 0; y < 27; y++) {
for (x = 0; x < 64; x++)
sorted[(y * 64) + x] = pixels[(y * 64) + (x >> 2) + ((x & 3) << 4)];
}
panelAmmo[3] = createSurface(sorted, 64, 27);
sorted = pixels; // Re-use the allocated memory
fseek(f, 12258, SEEK_SET);
pixels = loadRLE(f, 64 * 27);
for (y = 0; y < 27; y++) {
for (x = 0; x < 64; x++)
sorted[(y * 64) + x] = pixels[(y * 64) + (x >> 2) + ((x & 3) << 4)];
}
panelAmmo[4] = createSurface(sorted, 64, 27);
free(pixels);
fclose(f);
// Load real fonts
font2 = loadFont("font2.0fn");
fontbig = loadFont("fontbig.0fn");
fontiny = loadFont("fontiny.0fn");
fontmn1 = loadFont("fontmn1.0fn");
fontmn2 = loadFont("fontmn2.0fn");
firstPE = NULL;
return SUCCESS;
}
void usePalette (SDL_Color *palette) {
// Make palette changes invisible until the next draw. Hopefully.
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
SDL_Flip(screen);
SDL_SetPalette(screen, SDL_PHYSPAL, palette, 0, 256);
currentPalette = palette;
return;
}
void scalePalette (SDL_Surface *surface, fixed scale, signed int offset) {
SDL_Color palette[256];
int count;
for (count = 0; count < 256; count++) {
palette[count].r = ((count * scale) >> 10) + offset;
palette[count].g = ((count * scale) >> 10) + offset;
palette[count].b = ((count * scale) >> 10) + offset;
}
SDL_SetPalette(surface, SDL_LOGPAL, palette, 0, 256);
return;
}
void restorePalette (SDL_Surface *surface) {
SDL_SetPalette(surface, SDL_LOGPAL, logicalPalette, 0, 256);
return;
}
void releaseControl (int control) {
controls[control].time = oldTicks + 500;
controls[control].state = SDL_RELEASED;
return;
}
int loop (void) {
SDL_Event event;
paletteEffect *currentPE;
SDL_Color shownPalette[256];
int count, x, y;
#ifdef __GP2X__
unsigned long pad;
#endif
// Show everything that has been drawn so far
SDL_Flip(screen);
// Calculate frame rate and key timing
count = SDL_GetTicks();
fps = 1000.0f / ((float)(count - oldTicks));
if (count - oldTicks > 100) oldTicks = count - 100;
mspf = count - oldTicks;
oldTicks = count;
#ifdef __GP2X__
pad = gp2x_joystick_read();
#endif
// Process system events
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
#ifndef FULLSCREEN_ONLY
// If Alt + Enter has been pressed, go to full screen
if ((event.key.keysym.sym == SDLK_RETURN) &&
(event.key.keysym.mod & KMOD_ALT) ) {
fullscreen = !fullscreen;
if (fullscreen) {
SDL_ShowCursor(SDL_DISABLE);
screen = SDL_SetVideoMode(screenW, screenH, 8,
SDL_FULLSCREEN | SDL_DOUBLEBUF |
SDL_HWSURFACE | SDL_HWPALETTE);
SDL_SetPalette(screen, SDL_LOGPAL, logicalPalette, 0, 256);
SDL_SetPalette(screen, SDL_PHYSPAL, currentPalette, 0, 256);
// A real 8-bit display is quite likely if the user has the right
// video card, the right video drivers, the right version of
// DirectX/whatever, and the right version of SDL. In other words,
// it's not likely enough.
// If a real palette is assumed when
// a) There really is a real palette, there will be an extremely
// small speed gain
// b) The palette is emulated, there will be a HUGE speed loss
// Therefore, assume the palette is emulated
// To do: Find a better way!
fakePalette = 1;
} else {
screen = SDL_SetVideoMode(screenW, screenH, 8,
SDL_RESIZABLE | SDL_DOUBLEBUF |
SDL_HWSURFACE | SDL_HWPALETTE );
SDL_SetPalette(screen, SDL_LOGPAL, logicalPalette, 0, 256);
SDL_SetPalette(screen, SDL_PHYSPAL, currentPalette, 0, 256);
SDL_ShowCursor(SDL_ENABLE);
// Assume that in windowed mode the palette is being emulated
// This is extremely likely
// To do: Find a better way!
fakePalette = 1;
}
}
// The absence of a break statement is intentional
#endif
case SDL_KEYUP:
for (count = 0; count < CONTROLS; count++)
if (event.key.keysym.sym == keys[count].key)
keys[count].state = event.key.state;
break;
#ifdef __GP2X__
case SDL_JOYBUTTONDOWN:
if (pad & GP2X_DOWN) keys[K_DOWN].state = SDL_PRESSED;
if (pad & GP2X_UP) keys[K_UP].state = SDL_PRESSED;
if (pad & GP2X_LEFT) keys[K_LEFT].state = SDL_PRESSED;
if (pad & GP2X_RIGHT) keys[K_RIGHT].state = SDL_PRESSED;
if (pad & GP2X_A) keys[K_JUMP].state = SDL_PRESSED;
if (pad & GP2X_B) keys[K_FIRE].state = SDL_PRESSED;
if (pad & GP2X_Y) keys[K_CHANGE].state = SDL_PRESSED;
if (pad & GP2X_START) keys[K_ESCAPE].state = SDL_PRESSED;
break;
case SDL_JOYBUTTONUP:
if (!(pad & GP2X_DOWN)) keys[K_DOWN].state = SDL_RELEASED;
if (!(pad & GP2X_UP)) keys[K_UP].state = SDL_RELEASED;
if (!(pad & GP2X_LEFT)) keys[K_LEFT].state = SDL_RELEASED;
if (!(pad & GP2X_RIGHT)) keys[K_RIGHT].state = SDL_RELEASED;
if (!(pad & GP2X_A)) keys[K_JUMP].state = SDL_RELEASED;
if (!(pad & GP2X_B)) keys[K_FIRE].state = SDL_RELEASED;
if (!(pad & GP2X_Y)) keys[K_CHANGE].state = SDL_RELEASED;
break;
#endif
#if !defined(__GP2X__) && !defined(_arch_dreamcast)
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
for (count = 0; count < CONTROLS; count++)
if (event.jbutton.button == buttons[count].button)
buttons[count].state = event.jbutton.state;
break;
case SDL_JOYAXISMOTION:
for (count = 0; count < CONTROLS; count++)
if (event.jaxis.axis == axes[count].axis) {
if (!axes[count].direction && (event.jaxis.value < -16384))
axes[count].state = SDL_PRESSED;
else if (axes[count].direction && (event.jaxis.value > 16384))
axes[count].state = SDL_PRESSED;
else axes[count].state = SDL_RELEASED;
}
break;
#endif
#ifndef FULLSCREEN_ONLY
case SDL_VIDEORESIZE:
screenW = event.resize.w;
screenH = event.resize.h;
if (screenW > 320) bgScale = ((screenH - 1) / 100) + 1;
else bgScale = ((screenH - 34) / 100) + 1;
screen = SDL_SetVideoMode(screenW, screenH, 8,
SDL_RESIZABLE | SDL_DOUBLEBUF |
SDL_HWSURFACE | SDL_HWPALETTE );
// The absence of a break statement is intentional
case SDL_VIDEOEXPOSE:
SDL_SetPalette(screen, SDL_LOGPAL, logicalPalette, 0, 256);
SDL_SetPalette(screen, SDL_PHYSPAL, currentPalette, 0, 256);
break;
#endif
case SDL_QUIT:
return QUIT;
}
}
// Apply controls to universal control tracking
for (count = 0; count < CONTROLS; count++) {
if ((keys[count].state == SDL_PRESSED) ||
(buttons[count].state == SDL_PRESSED) ||
(axes[count].state == SDL_PRESSED) ) {
if (controls[count].time < oldTicks) controls[count].state = SDL_PRESSED;
} else {
controls[count].time = 0;
controls[count].state = SDL_RELEASED;
}
}
// Apply palette effects
currentPE = firstPE;
// If the palette is being emulated, compile all palette changes and apply
// them all at once.
// If the palette is being used directly, apply all palette effects directly
if (fakePalette) {
memcpy(shownPalette, currentPalette, sizeof(SDL_Color) << 8);
while (currentPE) {
switch (currentPE->type) {
case PE_FADE:
if (currentPE->position) {
for (count = currentPE->first;
count < currentPE->first + currentPE->amount; count++) {
shownPalette[count].r = (currentPalette[count].r *
currentPE->position) >> 10;
shownPalette[count].g = (currentPalette[count].g *
currentPE->position) >> 10;
shownPalette[count].b = (currentPalette[count].b *
currentPE->position) >> 10;
}
currentPE->position -= (mspf << 10) / currentPE->speed;
} else {
memset(shownPalette + currentPE->first, 0,
sizeof(SDL_Color) * currentPE->amount);
}
break;
case PE_1D:
currentPE->position = currentPE->amount - 1 -
(((currentPE->position * currentPE->speed) >>
10)
% currentPE->amount );
// The lack of a break statement is intentional
case PE_ROTATE:
for (count = 0; count < currentPE->amount; count++) {
memcpy(shownPalette + currentPE->first + count,
currentPalette + currentPE->first +
((count + (currentPE->position >> 10)) % currentPE->amount),
sizeof(SDL_Color));
}
currentPE->position -= (mspf * currentPE->speed) >> 10;
while (currentPE->position < 0)
currentPE->position += currentPE->amount << 10;
break;
case PE_SKY:
count = (((currentPE->position * currentPE->speed) / bgScale) >> 20) %
255;
if (count > 255 - currentPE->amount) {
memcpy(shownPalette + currentPE->first, skyPalette + count,
sizeof(SDL_Color) * (255 - count));
memcpy(shownPalette + currentPE->first + (255 - count), skyPalette,
sizeof(SDL_Color) * (count + currentPE->amount - 255));
} else {
memcpy(shownPalette + currentPE->first, skyPalette + count,
sizeof(SDL_Color) * currentPE->amount);
}
break;
case PE_2D:
x = (((256 * 32) - *((short int *)&(currentPE->position))) *
currentPE->speed) >> 10;
y = (((64 * 32) - *((short int *)&(currentPE->position) + 1)) *
currentPE->speed) >> 10;
for (count = 0; count < currentPE->amount >> 3; count++) {
int j;
for (j = 0; j < 8; j++) {
memcpy(shownPalette + currentPE->first + (count << 3) + j,
currentPalette + currentPE->first +
(((count + y) % 8) << 3) + ((j + x) % 8),
sizeof(SDL_Color));
}
}
break;
case PE_WATER:
// To do: Underwater darkness palette effect
break;
}
currentPE = currentPE->next;
}
if (firstPE) SDL_SetPalette(screen, SDL_PHYSPAL, shownPalette, 0, 256);
} else {
while (currentPE) {
switch (currentPE->type) {
case PE_FADE:
if (currentPE->position) {
for (count = currentPE->first;
count < currentPE->first + currentPE->amount; count++) {
shownPalette[count].r = (currentPalette[count].r *
currentPE->position) >> 10;
shownPalette[count].g = (currentPalette[count].g *
currentPE->position) >> 10;
shownPalette[count].b = (currentPalette[count].b *
currentPE->position) >> 10;
}
currentPE->position -= (mspf << 10) / currentPE->speed;
} else {
memset(shownPalette + currentPE->first, 0,
sizeof(SDL_Color) * currentPE->amount);
}
SDL_SetPalette(screen, SDL_PHYSPAL, shownPalette + currentPE->first,
currentPE->first, currentPE->amount);
break;
case PE_1D:
currentPE->position = currentPE->amount - 1 -
(((currentPE->position * currentPE->speed) >>
10)
% currentPE->amount );
// The lack of a break statement is intentional
case PE_ROTATE:
for (count = 0; count < currentPE->amount; count++) {
memcpy(shownPalette + currentPE->first + count,
currentPalette + currentPE->first +
((count + (currentPE->position >> 10)) % currentPE->amount),
sizeof(SDL_Color));
}
currentPE->position -= (mspf * currentPE->speed) >> 10;
while (currentPE->position < 0)
currentPE->position += currentPE->amount << 10;
SDL_SetPalette(screen, SDL_PHYSPAL, shownPalette + currentPE->first,
currentPE->first, currentPE->amount);
break;
case PE_SKY:
count = (((currentPE->position * currentPE->speed) / bgScale) >> 20) %
255;
if (count > 255 - currentPE->amount) {
SDL_SetPalette(screen, SDL_PHYSPAL, skyPalette + count,
currentPE->first, 255 - count);
SDL_SetPalette(screen, SDL_PHYSPAL, skyPalette,
currentPE->first + (255 - count),
count + currentPE->amount - 255);
} else {
SDL_SetPalette(screen, SDL_PHYSPAL, skyPalette + count,
currentPE->first, currentPE->amount);
}
break;
case PE_2D:
x = (((256 * 32) - *((short int *)&(currentPE->position))) *
currentPE->speed) >> 10;
y = (((64 * 32) - *((short int *)&(currentPE->position) + 1)) *
currentPE->speed) >> 10;
for (count = 0; count < currentPE->amount >> 3; count++) {
int j;
for (j = 0; j < 8; j++) {
memcpy(shownPalette + currentPE->first + (count << 3) + j,
currentPalette + currentPE->first +
(((count + y) % 8) << 3) + ((j + x) % 8),
sizeof(SDL_Color));
}
}
SDL_SetPalette(screen, SDL_PHYSPAL, shownPalette + currentPE->first,
currentPE->first, currentPE->amount);
break;
case PE_WATER:
// To do: Underwater darkness palette effect
break;
}
currentPE = currentPE->next;
}
}
return SUCCESS;
}
void freeMain (void) {
SDL_FreeSurface(panel);
SDL_FreeSurface(panelBigFont.pixels);
free(panelBigFont.w);
SDL_FreeSurface(panelSmallFont.pixels);
free(panelSmallFont.w);
freeFont(font2);
freeFont(fontbig);
freeFont(fontiny);
freeFont(fontmn1);
freeFont(fontmn2);
SDL_FreeSurface(panelAmmo[0]);
SDL_FreeSurface(panelAmmo[1]);
SDL_FreeSurface(panelAmmo[2]);
SDL_FreeSurface(panelAmmo[3]);
SDL_FreeSurface(panelAmmo[4]);
free(currentLevel);
free(nextLevel);
free(path);
return;
}
int main(int argc, char *argv[]) {
int count;
#ifdef GP32
x_gp32_SetCPUSpeed_133();
#endif
// Find path
#if !defined(_arch_dreamcast) && !defined(GP32)
if (argc < 2) {
int count;
count = strlen(argv[0]) - 1;
#ifdef WIN32
while ((argv[0][count] != '\\') && (count >= 0)) count--;
#else
#ifdef __MACH__
count = (unsigned int)(strstr(argv[0], "app/Contents/MacOS") - argv[0]);
#endif
while ((argv[0][count] != '/') && (count >= 0)) count--;
#endif
path = malloc(count + 2);
if (count >= 0) {
memcpy(path, argv[0], count + 1);
path[count + 1] = 0;
} else path[0] = 0;
} else {
#ifdef WIN32
if (argv[1][strlen(argv[1]) - 1] != '\\') {
#else
if (argv[1][strlen(argv[1]) - 1] != '/') {
#endif
path = malloc(strlen(argv[1]) + 2);
strcpy(path, argv[1]);
#ifdef WIN32
strcat(path, "\\");
#else
strcat(path, "/");
#endif
} else {
path = malloc(strlen(argv[1]) + 1);
strcpy(path, argv[1]);
}
}
#endif
#ifdef _arch_dreamcast
path = malloc(5);
strcpy(path, "/cd/");
#endif
#ifdef GP32
path = malloc(12);
strcpy(path, DATA_PREFIX);
#endif
// Initialise global variables
keys[C_ENTER].key = SDLK_RETURN;
keys[C_ESCAPE].key = SDLK_ESCAPE;
// To do: Load controls from config file
#ifdef GP32
keys[C_UP].key = SDLK_UP;
keys[C_DOWN].key = SDLK_DOWN;
keys[C_LEFT].key = SDLK_LEFT;
keys[C_RIGHT].key = SDLK_RIGHT;
keys[C_JUMP].key = SDLK_LCTRL;
keys[C_FIRE].key = SDLK_LALT;
keys[C_CHANGE].key = SDLK_SPACE;
#else
keys[C_UP].key = SDLK_UP;
keys[C_DOWN].key = SDLK_DOWN;
keys[C_LEFT].key = SDLK_LEFT;
keys[C_RIGHT].key = SDLK_RIGHT;
#ifdef WIN32
keys[C_JUMP].key = SDLK_RALT;
keys[C_FIRE].key = SDLK_SPACE;
#else
keys[C_JUMP].key = SDLK_SPACE;
keys[C_FIRE].key = SDLK_LALT;
#endif
keys[C_CHANGE].key = SDLK_RCTRL;
#endif
buttons[C_UP].button = -1;
buttons[C_DOWN].button = -1;
buttons[C_LEFT].button = -1;
buttons[C_RIGHT].button = -1;
buttons[C_JUMP].button = 1;
buttons[C_FIRE].button = 0;
buttons[C_CHANGE].button = 3;
buttons[C_ENTER].button = 0;
buttons[C_ESCAPE].button = -1;
axes[C_UP].axis = 1;
axes[C_UP].direction = 0;
axes[C_DOWN].axis = 1;
axes[C_DOWN].direction = 1;
axes[C_LEFT].axis = 0;
axes[C_LEFT].direction = 0;
axes[C_RIGHT].axis = 0;
axes[C_RIGHT].direction = 1;
axes[C_JUMP].axis = -1;
axes[C_FIRE].axis = -1;
axes[C_CHANGE].axis = -1;
axes[C_ENTER].axis = -1;
axes[C_ESCAPE].axis = -1;
for (count = 0; count < CONTROLS; count++) {
controls[count].time = 0;
controls[count].state= SDL_RELEASED;
}
// To do: Load resolution from config file
screenW = 320;
screenH = 200;
#ifndef FULLSCREEN_ONLY
fullscreen = 0;
#endif
bgScale = 2;
mspf = 20;
fps = 50.0f; // Arbitrarily chosen starting speed
#ifdef __GP2X__
gp2x_init(1000, 16, 11025, 16, 1, 60, 1);
#endif
// Initialise SDL
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK |
SDL_INIT_TIMER ) < 0) {
fprintf(stderr, "Could not start SDL: %s\n", SDL_GetError());
return -1;
}
// Create the game's window
#ifdef FULLSCREEN_ONLY
#ifdef __GP2X__
if ((screen = SDL_SetVideoMode(screenW, screenH, 8, SDL_SWSURFACE)) == NULL) {
#else
if ((screen = SDL_SetVideoMode(screenW, screenH, 8,
SDL_FULLSCREEN | SDL_DOUBLEBUF |
SDL_HWSURFACE | SDL_HWPALETTE )) == NULL) {
#endif
#else
if ((screen = SDL_SetVideoMode(screenW, screenH, 8,
SDL_RESIZABLE | SDL_DOUBLEBUF |
SDL_HWSURFACE | SDL_HWPALETTE )) == NULL) {
#endif
fprintf(stderr, "Could not set video mode: %s\n", SDL_GetError());
return -1;
}
if (SDL_NumJoysticks() > 0) SDL_JoystickOpen(0);
#ifdef _arch_dreamcast
// Map dreamcast controls to the keyboard
SDL_DC_SetVideoDriver(SDL_DC_DIRECT_VIDEO);
SDL_DC_VerticalWait(SDL_FALSE);
SDL_DC_EmulateKeyboard(SDL_TRUE);
SDL_DC_MapKey(0, SDL_DC_LEFT, SDLK_LEFT);
SDL_DC_MapKey(0, SDL_DC_RIGHT, SDLK_RIGHT);
SDL_DC_MapKey(0, SDL_DC_UP, SDLK_UP);
SDL_DC_MapKey(0, SDL_DC_DOWN, SDLK_DOWN);
SDL_DC_MapKey(0, SDL_DC_START, SDLK_RETURN);
SDL_DC_MapKey(0, SDL_DC_A, SDLK_SPACE);
SDL_DC_MapKey(0, SDL_DC_X, SDLK_LALT);
SDL_DC_MapKey(0, SDL_DC_Y, SDLK_LALT);
SDL_DC_MapKey(0, SDL_DC_B, SDLK_SPACE);
#endif
#ifdef __GP2X__
SDL_ShowCursor(0);
#endif
// Assume that in windowed mode the palette is being emulated
// This is extremely likely
// To do: Find a better way!
fakePalette = 1;
SDL_WM_SetCaption("OpenJazz", NULL);
// Load universal game data
if (loadMain()) {
SDL_Quit();
return -1;
}
// Establish timing
oldTicks = SDL_GetTicks() - 20;
// Show the startup cutscene
// if (runScene("startup.0sc") != QUIT) {
// Run the menu
if (runMenu() != QUIT) {
// Show the ending cutscene
// runScene("end.0sc");
}
// }
SDL_Quit();
#ifdef __GP2X__
chdir("/usr/gp2x");
execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);
#endif
return 0;
}