666 lines
20 KiB
C
666 lines
20 KiB
C
/*
|
|
*
|
|
* Singe 2
|
|
* Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
|
|
// -c -x 720 -y 480 -d data/maddog_dvd -v maddog_dvd/frame_maddog_dvd.txt maddog_dvd/maddog_dvd.singe
|
|
// -c -x 640 -y 480 -v ActionMax/frame_SonicFury.txt ActionMax/SonicFury.singe
|
|
// -x 640 -y 480 -d data/ActionMax ActionMax/BlueThunder.singe
|
|
// -d data/ActionMax -v ActionMax/BlueThunder.mp4 test.singe
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <SDL2/SDL.h>
|
|
#include <SDL2/SDL_image.h>
|
|
#include <SDL2/SDL_mixer.h>
|
|
#include <SDL2/SDL_ttf.h>
|
|
#include <carg_parser.h>
|
|
#include <manymouse.h>
|
|
|
|
#include "stddclmr.h"
|
|
#include "common.h"
|
|
#include "util.h"
|
|
#include "frameFile.h"
|
|
#include "videoPlayer.h"
|
|
#include "singe.h"
|
|
#include "extensions.h"
|
|
#include "embedded.h"
|
|
|
|
|
|
typedef struct RatioS {
|
|
int32_t aspectNum;
|
|
int32_t aspectDom;
|
|
} RatioT;
|
|
|
|
typedef struct ResolutionS {
|
|
int32_t width;
|
|
int32_t height;
|
|
} ResolutionT;
|
|
|
|
typedef struct ModeS {
|
|
RatioT ratio;
|
|
ResolutionT resolution;
|
|
} ModeT;
|
|
|
|
|
|
bool extractFile(char *filename, unsigned char *data, int32_t length);
|
|
void showUsage(char *name, char *message);
|
|
|
|
|
|
bool extractFile(char *filename, unsigned char *data, int32_t length) {
|
|
FILE *out;
|
|
|
|
if (!utilFileExists(filename)) {
|
|
out = fopen(filename, "wb");
|
|
if (!out) utilDie("Unable to create %s", filename);
|
|
fwrite(data, length, 1, out);
|
|
fclose(out);
|
|
utilSay("Created File: %s", filename);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
__attribute__((noreturn))
|
|
void showUsage(char *name, char *message) {
|
|
char *temp = NULL;
|
|
bool created = false;
|
|
int32_t result = 0;
|
|
|
|
utilRedirectConsole();
|
|
|
|
// 00000000011111111112222222222333333333344444444445555555555666666666677777777778
|
|
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
utilSay(" ___ ___ _ _ ___ ___");
|
|
utilSay("/ __|_ _| \\| |/ __| __| Somewhat Interactive Nostalgic Game Engine %s", VERSION_STRING);
|
|
utilSay("\\__ \\| || .` | (_ | _| Copyright (c) 2006-%s Scott C. Duensing", COPYRIGHT_END_YEAR);
|
|
utilSay("|___/___|_|\\_|\\___|___| https://kangaroopunch.com");
|
|
utilSay("");
|
|
utilSay("Usage: %s [OPTIONS] scriptName{.singe}", utilGetLastPathComponent(name));
|
|
utilSay("");
|
|
utilSay(" -a, --aspect=N:D force aspect ratio");
|
|
utilSay(" -c, --showcalculated show calculated framefile values for debugging");
|
|
utilSay(" -d, --datadir=PATHNAME alternate location for written files");
|
|
utilSay(" -e, --volume_nonvldp=PERCENT specify sound effects volume in percent");
|
|
utilSay(" -f, --fullscreen run in full screen mode");
|
|
utilSay(" -g, --sindengun=PARAMS enable Sinden Light Gun support");
|
|
utilSay(" -h, --help this display");
|
|
utilSay(" -k, --nologos kill the splash screens");
|
|
utilSay(" -l, --volume_vldp=PERCENT specify laserdisc volume in percent");
|
|
utilSay(" -m, --nomouse disable mouse");
|
|
utilSay(" -o, --scalefactor=PERCENT reduce screen size for overscan compensation");
|
|
utilSay(" -s, --nosound, --mutesound mutes all sound");
|
|
utilSay(" -t, --trace trace script execution to screen and file");
|
|
utilSay(" -u, --stretch use ugly stretched video");
|
|
utilSay(" -v, --framefile=FILENAME use an alternate video file");
|
|
utilSay(" -w, --fullscreen_window run in windowed full screen mode");
|
|
utilSay(" -x, --xresolution=VALUE specify horizontal resolution");
|
|
utilSay(" -y, --yresolution=VALUE specify vertical resolution");
|
|
utilSay(" -z, --noconsole zero console output");
|
|
utilSay("");
|
|
|
|
// Extract any missing support files. We do this here so they're not generated if launched from a front end.
|
|
if (!utilPathExists("Singe")) utilMkDirP("Singe", 0777);
|
|
// Singe/Framework.singe
|
|
temp = utilCreateString("Singe%cFramework.singe", utilGetPathSeparator());
|
|
created |= extractFile(temp, Framework_singe, Framework_singe_len);
|
|
free(temp);
|
|
// Singe/controls.cfg.example
|
|
temp = utilCreateString("Singe%ccontrols.cfg.example", utilGetPathSeparator());
|
|
created |= extractFile(temp, controls_cfg, controls_cfg_len);
|
|
free(temp);
|
|
temp = NULL;
|
|
|
|
if (created) utilSay("");
|
|
|
|
if (message) {
|
|
utilSay("Error: %s", message);
|
|
utilSay("");
|
|
result = 1;
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
getchar();
|
|
#endif
|
|
exit(result);
|
|
}
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
int32_t x = 0;
|
|
int32_t err = 0;
|
|
int32_t flags = 0;
|
|
int32_t bestResIndex = -1;
|
|
int32_t bestRatioIndex = -1;
|
|
int32_t aspectNum = -1;
|
|
int32_t aspectDom = -1;
|
|
int32_t argCount = 0;
|
|
int32_t argIndex = 0;
|
|
int32_t code = 0;
|
|
char *exeName = NULL;
|
|
char *temp = NULL;
|
|
char *aspectString = NULL;
|
|
char *sindenString = NULL;
|
|
float thisRatio = 0;
|
|
float bestRatio = 9999;
|
|
bool tracing = false;
|
|
SDL_Window *window = NULL;
|
|
SDL_Renderer *renderer = NULL;
|
|
SDL_Surface *icon = NULL;
|
|
SDL_DisplayMode mode;
|
|
const char *arg = NULL;
|
|
const char **cargv = (const char **)argv;
|
|
struct Arg_parser parser;
|
|
static struct ap_Option options[] = {
|
|
{ 'a', "aspect", ap_yes },
|
|
{ 'c', "showcalculated", ap_no },
|
|
{ 'd', "datadir", ap_yes },
|
|
{ 'e', "volume_nonlvdp", ap_yes },
|
|
{ 'f', "fullscreen", ap_no },
|
|
{ 'g', "sindengun", ap_yes },
|
|
{ 'h', "help", ap_no },
|
|
{ 'k', "nologos", ap_no },
|
|
{ 'l', "volume_vldp", ap_yes },
|
|
{ 'm', "nomouse", ap_no },
|
|
{ 'o', "scalefactor", ap_yes },
|
|
{ 's', "nosound", ap_no },
|
|
{ 't', "trace", ap_no },
|
|
{ 'u', "stretch", ap_no },
|
|
{ 'v', "framefile", ap_yes },
|
|
{ 'w', "fullscreenwindow", ap_no },
|
|
{ 'x', "xresolution", ap_yes },
|
|
{ 'y', "yresolution", ap_yes },
|
|
{ 'z', "noconsole", ap_no },
|
|
{ 0, 0, ap_no }
|
|
};
|
|
static ModeT modes[] = {
|
|
{ { 4, 3 }, { 640, 480 } },
|
|
{ { 4, 3 }, { 800, 600 } },
|
|
{ { 4, 3 }, { 960, 720 } },
|
|
{ { 4, 3 }, { 1024, 768 } },
|
|
{ { 4, 3 }, { 1280, 960 } },
|
|
{ { 4, 3 }, { 1400, 1050 } },
|
|
{ { 4, 3 }, { 1440, 1080 } },
|
|
{ { 4, 3 }, { 1600, 1200 } },
|
|
{ { 4, 3 }, { 1856, 1392 } },
|
|
{ { 4, 3 }, { 1920, 1440 } },
|
|
{ { 4, 3 }, { 2048, 1536 } },
|
|
{ { 16, 9 }, { 1024, 576 } },
|
|
{ { 16, 9 }, { 1152, 648 } },
|
|
{ { 16, 9 }, { 1280, 720 } },
|
|
{ { 16, 9 }, { 1366, 768 } },
|
|
{ { 16, 9 }, { 1600, 900 } },
|
|
{ { 16, 9 }, { 1920, 1080 } },
|
|
{ { 16, 9 }, { 2560, 1440 } },
|
|
{ { 16, 9 }, { 3840, 2160 } },
|
|
{ { 16, 9 }, { 7680, 4320 } },
|
|
{ { 16, 10 }, { 1280, 800 } },
|
|
{ { 16, 10 }, { 1440, 900 } },
|
|
{ { 16, 10 }, { 1680, 1050 } },
|
|
{ { 16, 10 }, { 1920, 1200 } },
|
|
{ { 16, 10 }, { 2560, 1600 } },
|
|
{ { 0, 0 }, { 0, 0 } }
|
|
};
|
|
|
|
exeName = (char *)argv[0];
|
|
|
|
if (!ap_init(&parser, argc, cargv, options, 0)) {
|
|
utilDie("Out of memory parsing arguments.");
|
|
}
|
|
if (ap_error(&parser)) {
|
|
utilDie("%s", ap_error(&parser));
|
|
}
|
|
|
|
// Parse command line
|
|
argCount = ap_arguments(&parser);
|
|
for (argIndex=0; argIndex < ap_arguments(&parser); ++argIndex) {
|
|
|
|
code = ap_code(&parser, argIndex);
|
|
if (!code) break;
|
|
arg = ap_argument(&parser, argIndex);
|
|
|
|
// Handle options
|
|
switch (code) {
|
|
|
|
// Aspect
|
|
case 'a':
|
|
if (aspectString) free(aspectString);
|
|
aspectString = strdup(arg);
|
|
argCount++;
|
|
break;
|
|
|
|
// Show Calculated Frame File Values
|
|
case 'c':
|
|
_confShowCalculated = true;
|
|
break;
|
|
|
|
// Data Dir
|
|
case 'd':
|
|
if (_confDataDir) free(_confDataDir);
|
|
_confDataDir = strdup(arg);
|
|
argCount++;
|
|
break;
|
|
|
|
// Effects Volume
|
|
case 'e':
|
|
_confVolumeNonVldp = atoi(arg);
|
|
argCount++;
|
|
break;
|
|
|
|
// Full Screen
|
|
case 'f':
|
|
_confFullScreen = true;
|
|
break;
|
|
|
|
// Sinden Light Gun
|
|
case 'g':
|
|
if (sindenString) free(sindenString);
|
|
sindenString = strdup(arg);
|
|
argCount++;
|
|
break;
|
|
|
|
// Help
|
|
case 'h':
|
|
showUsage(exeName, NULL);
|
|
break;
|
|
|
|
// No Logos
|
|
case 'k':
|
|
_confNoLogos = true;
|
|
break;
|
|
|
|
// Video Volume
|
|
case 'l':
|
|
_confVolumeVldp = atoi(arg);
|
|
argCount++;
|
|
break;
|
|
|
|
// No Mouse
|
|
case 'm':
|
|
_confNoMouse = true;
|
|
break;
|
|
|
|
// Overscan Zoom
|
|
case 'o':
|
|
_confScaleFactor = atoi(arg);
|
|
argCount++;
|
|
break;
|
|
|
|
// No Sound
|
|
case 's':
|
|
_confNoSound = true;
|
|
break;
|
|
|
|
// Trace
|
|
case 't':
|
|
tracing = true;
|
|
break;
|
|
|
|
// Ugly Stretched Video
|
|
case 'u':
|
|
_confStretchVideo = true;
|
|
break;
|
|
|
|
// Video File
|
|
case 'v':
|
|
if (_confVideoFile) free(_confVideoFile);
|
|
_confVideoFile = strdup(arg);
|
|
argCount++;
|
|
break;
|
|
|
|
// Full Screen Windowed
|
|
case 'w':
|
|
_confFullScreenWindow = true;
|
|
break;
|
|
|
|
// X Resolution
|
|
case 'x':
|
|
_confXResolution = atoi(arg);
|
|
argCount++;
|
|
break;
|
|
|
|
// Y Resolution
|
|
case 'y':
|
|
_confYResolution = atoi(arg);
|
|
argCount++;
|
|
break;
|
|
|
|
// No console output or splash screens
|
|
case 'z':
|
|
_confNoConsole = true;
|
|
break;
|
|
|
|
default:
|
|
abort(); // Something bad happened
|
|
break;
|
|
}
|
|
}
|
|
|
|
// For that dumb OS
|
|
if (!_confNoConsole) utilRedirectConsole();
|
|
|
|
// Did we get a filename or path to open?
|
|
if ((argc - argCount) != 1) showUsage(exeName, "No script file specified.");
|
|
_confScriptFile = strdup(argv[argCount]);
|
|
utilFixPathSeparators(&_confScriptFile, false);
|
|
// Exists?
|
|
if (!utilFileExists(_confScriptFile)) {
|
|
// Missing. Is a path?
|
|
if (utilPathExists(_confScriptFile)) {
|
|
// See if the script exists in the path.
|
|
temp = utilCreateString("%s%c%s.singe", _confScriptFile, utilGetPathSeparator(), utilGetLastPathComponent(_confScriptFile));
|
|
if (utilFileExists(temp)) {
|
|
// Found script named for path inside path.
|
|
free(_confScriptFile);
|
|
_confScriptFile = temp;
|
|
temp = NULL;
|
|
} else {
|
|
// Not in the path either.
|
|
free(_confScriptFile);
|
|
_confScriptFile = NULL;
|
|
}
|
|
} else {
|
|
// Not a path either.
|
|
free(_confScriptFile);
|
|
_confScriptFile = NULL;
|
|
}
|
|
}
|
|
if (!_confScriptFile) showUsage(exeName, "Unable to locate script.");
|
|
|
|
// Do we need to generate a video name?
|
|
if (_confVideoFile) {
|
|
utilFixPathSeparators(&_confVideoFile, false);
|
|
if (!utilFileExists(_confVideoFile)) {
|
|
free(_confVideoFile);
|
|
_confVideoFile = NULL;
|
|
}
|
|
} else {
|
|
x = (int32_t)(strlen(_confScriptFile) - strlen(utilGetFileExtension(_confScriptFile))) - 1;
|
|
if (x < 0) {
|
|
x = 0;
|
|
}
|
|
temp = strdup(_confScriptFile);
|
|
temp[x] = 0;
|
|
// Check all known extensions - lower case only, Windows users!
|
|
x = 0;
|
|
while (ffmpegExtensions[x]) {
|
|
_confVideoFile = utilCreateString("%s.%s", temp, ffmpegExtensions[x]);
|
|
if (utilFileExists(_confVideoFile)) {
|
|
break;
|
|
}
|
|
free(_confVideoFile);
|
|
_confVideoFile = NULL;
|
|
x++;
|
|
}
|
|
free(temp);
|
|
// If we still don't have one, try a framefile
|
|
if (!_confVideoFile) {
|
|
_confVideoFile = utilCreateString("%s.txt", temp);
|
|
if (!utilFileExists(_confVideoFile)) {
|
|
free(_confVideoFile);
|
|
_confVideoFile = NULL;
|
|
}
|
|
}
|
|
}
|
|
if (!_confVideoFile) showUsage(exeName, "Unable to locate video.");
|
|
// Is it a framefile?
|
|
if (strncmp(utilGetFileExtension(_confVideoFile), "txt", 3) == 0) {
|
|
_confIsFrameFile = true;
|
|
}
|
|
|
|
// Do we need to generate a data directory name?
|
|
if (_confDataDir) {
|
|
utilFixPathSeparators(&_confDataDir, false);
|
|
// Try to create data directory to ensure it exists.
|
|
utilMkDirP(_confDataDir, 0777);
|
|
// Does it exist?
|
|
if (!utilPathExists(_confDataDir)) {
|
|
free(_confDataDir);
|
|
_confDataDir = NULL;
|
|
}
|
|
} else {
|
|
// Put it in the game folder.
|
|
x = (int32_t)(strlen(_confScriptFile) - strlen(utilGetLastPathComponent(_confScriptFile))) - 1;
|
|
if (x < 0) {
|
|
x = 0;
|
|
}
|
|
temp = strdup(_confScriptFile);
|
|
temp[x] = 0;
|
|
_confDataDir = strdup(temp);
|
|
free(temp);
|
|
temp = NULL;
|
|
}
|
|
if (!_confDataDir) showUsage(exeName, "Unable to locate data directory.");
|
|
utilFixPathSeparators(&_confDataDir, true);
|
|
|
|
// Do they want tracing?
|
|
if (tracing) {
|
|
temp = utilCreateString("%strace.txt", _confDataDir);
|
|
utilTraceStart(temp);
|
|
free(temp);
|
|
temp = NULL;
|
|
}
|
|
|
|
// Do the full screen options make sense?
|
|
if (_confFullScreen && _confFullScreenWindow) showUsage(exeName, "Full Screen or Full Screen Windowed. Pick one.");
|
|
|
|
// Sane volume values?
|
|
if ((_confVolumeVldp < 0) || (_confVolumeVldp > 100)) showUsage(exeName, "Laserdisc volume must be between 0 and 100 percent.");
|
|
if ((_confVolumeNonVldp < 0) || (_confVolumeNonVldp > 100)) showUsage(exeName, "Effects volume must be between 0 and 100 percent.");
|
|
|
|
// Sane scale factor?
|
|
if ((_confScaleFactor < 50) || (_confScaleFactor > 100)) showUsage(exeName, "Display scale must be between 50 and 100 percent.");
|
|
|
|
// Sinden light gun?
|
|
if (sindenString) {
|
|
if (_confScaleFactor != 100) showUsage(exeName, "Cannot use --sindengun and --scalefactor together.");
|
|
// Was it wrapped in quotes?
|
|
if ((sindenString[0] == '"') || (sindenString[0] == '\'')) {
|
|
sindenString[0] = ' ';
|
|
}
|
|
// Ok, this thing can have a mess of different arguments:
|
|
// WW - Just the width of the white border
|
|
// WW WB - Width of white border and then black border
|
|
// RW GW BW WW - Custom color "white" border and width
|
|
// RW GW BW WW WB - Custom color "white" border and width then width of black border
|
|
// RW GW BW WW RB GB BB WB - Custom color "white" border and width then custom color "black" border and width
|
|
temp = strtok(sindenString, " ");
|
|
while (temp != NULL) {
|
|
_confSindenArgv[_confSindenArgc++] = atoi(temp);
|
|
temp = strtok(NULL, " ");
|
|
if ((temp != NULL) && (_confSindenArgc > SINDEN_OPTION_COUNT)) showUsage(exeName, "Too many arguments to --sindengun.");
|
|
}
|
|
// Did we get a sane number of arguments?
|
|
if ((_confSindenArgc != SINDEN_WHITE) && (_confSindenArgc != SINDEN_WHITE_BLACK) && (_confSindenArgc != SINDEN_CUSTOM_WHITE) && (_confSindenArgc != SINDEN_CUSTOM_WHITE_BLACK) && (_confSindenArgc != SINDEN_CUSTOM_WHITE_CUSTOM_BLACK)) showUsage(exeName, "Bad argument count to --sindengun.");
|
|
free(sindenString);
|
|
}
|
|
|
|
// Init SDL
|
|
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) utilDie("%s", SDL_GetError());
|
|
if (SDL_GetCurrentDisplayMode(0, &mode) < 0) utilDie("%s", SDL_GetError());
|
|
|
|
// Determine resolution if not specified
|
|
if ((_confXResolution <= 0) || (_confYResolution <= 0)) {
|
|
// Did they specify an aspect ratio?
|
|
if (aspectString) {
|
|
aspectNum = atoi(aspectString);
|
|
temp = strstr(aspectString, ":");
|
|
if (temp) {
|
|
temp++;
|
|
aspectDom = atoi(temp);
|
|
temp = NULL;
|
|
}
|
|
if ((aspectNum > 0) && (aspectDom > 0)) {
|
|
// Do we understand what they asked for?
|
|
x = 0;
|
|
while (modes[x].ratio.aspectNum != 0) {
|
|
if ((modes[x].ratio.aspectNum == aspectNum) && (modes[x].ratio.aspectDom == aspectDom)) {
|
|
bestRatioIndex = x;
|
|
break;
|
|
}
|
|
x++;
|
|
}
|
|
}
|
|
free(aspectString);
|
|
} else {
|
|
// Find our current aspect ratio
|
|
x = 0;
|
|
while (modes[x].ratio.aspectNum != 0) {
|
|
thisRatio = fabsf(((float)modes[x].ratio.aspectNum / (float)modes[x].ratio.aspectDom) - ((float)mode.w / (float)mode.h));
|
|
if (thisRatio < bestRatio) {
|
|
bestRatio = thisRatio;
|
|
bestRatioIndex = x;
|
|
}
|
|
x++;
|
|
}
|
|
}
|
|
if (bestRatioIndex < 0) showUsage(exeName, "Unknown aspect ratio.");
|
|
x = 0;
|
|
// Were both resolutions not specified?
|
|
if ((_confXResolution <= 0) && (_confYResolution <= 0)) {
|
|
// Are we full screen?
|
|
if (_confFullScreen || _confFullScreenWindow) {
|
|
// Use desktop resolution
|
|
_confXResolution = mode.w;
|
|
_confYResolution = mode.h;
|
|
} else {
|
|
// Find largest window that will fit on the screen but not fill it
|
|
while (modes[x].ratio.aspectNum != 0) {
|
|
if ((modes[x].ratio.aspectNum == modes[bestRatioIndex].ratio.aspectNum) && (modes[x].ratio.aspectDom == modes[bestRatioIndex].ratio.aspectDom)) {
|
|
if ((modes[x].resolution.width < mode.w) && (modes[x].resolution.height < mode.h)) {
|
|
bestResIndex = x;
|
|
}
|
|
}
|
|
x++;
|
|
}
|
|
_confXResolution = modes[bestResIndex].resolution.width;
|
|
_confYResolution = modes[bestResIndex].resolution.height;
|
|
}
|
|
} else {
|
|
// Find unprovided width/height using provided value
|
|
while (modes[x].ratio.aspectNum != 0) {
|
|
// Is this the aspect ratio we're using?
|
|
if ((modes[bestRatioIndex].ratio.aspectNum == modes[x].ratio.aspectNum) && (modes[bestRatioIndex].ratio.aspectDom == modes[x].ratio.aspectDom)) {
|
|
// Do we have the width or height?
|
|
if (_confXResolution > 0) {
|
|
// We have the width. Is this the matching entry?
|
|
if (modes[x].resolution.width == _confXResolution) {
|
|
bestResIndex = x;
|
|
_confYResolution = modes[x].resolution.height;
|
|
break;
|
|
}
|
|
} else {
|
|
// We have the height. Is this the matching entry?
|
|
if (modes[x].resolution.height == _confYResolution) {
|
|
bestResIndex = x;
|
|
_confXResolution = modes[x].resolution.width;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
x++;
|
|
}
|
|
}
|
|
}
|
|
// Did we end up with a valid resolution?
|
|
if (_confXResolution <= 0) showUsage(exeName, "Unable to determine X resolution. (Is the Y value sane?)");
|
|
if (_confYResolution <= 0) showUsage(exeName, "Unable to determine Y resolution. (Is the X value sane?)");
|
|
if ((_confXResolution > mode.w) || (_confYResolution > mode.h)) showUsage(exeName, "Specified resolution is larger than the display.");
|
|
|
|
// Init SDL_mixer ***FIX***
|
|
flags = /* MIX_INIT_FLAC | */ MIX_INIT_MOD | /* MIX_INIT_MP3 | */ MIX_INIT_OGG | MIX_INIT_MID | MIX_INIT_OPUS;
|
|
err = Mix_Init(flags);
|
|
if (err != flags) utilDie("%s", Mix_GetError());
|
|
|
|
// Init SDL_image ***FIX***
|
|
flags = IMG_INIT_JPG | IMG_INIT_PNG | /* IMG_INIT_TIF | */ IMG_INIT_WEBP;
|
|
err = IMG_Init(flags);
|
|
if (err != flags) utilDie("%s", IMG_GetError());
|
|
|
|
// Init SDL_ttf
|
|
if (TTF_Init() < 0) utilDie("%s", TTF_GetError());
|
|
|
|
// Create Resizable Window
|
|
window = SDL_CreateWindow("SINGE", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, _confXResolution, _confYResolution, SDL_WINDOW_RESIZABLE);
|
|
if (window == NULL) utilDie("%s", SDL_GetError());
|
|
|
|
// Window Icon
|
|
icon = IMG_LoadPNG_RW(SDL_RWFromMem(icon_png, icon_png_len));
|
|
if (icon == NULL) utilDie("%s", SDL_GetError());
|
|
SDL_SetWindowIcon(window, icon);
|
|
SDL_FreeSurface(icon);
|
|
icon = NULL;
|
|
|
|
// Do we want full screen of some kind?
|
|
if (_confFullScreen || _confFullScreenWindow) {
|
|
flags = _confFullScreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP;
|
|
SDL_SetWindowFullscreen(window, (Uint32)flags);
|
|
}
|
|
|
|
// Create an accelerated renderer.
|
|
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
|
if (renderer == NULL) utilDie("%s", SDL_GetError());
|
|
|
|
// Clear screen with black
|
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
|
SDL_RenderClear(renderer);
|
|
|
|
// Create audio mixer device
|
|
err = Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 44100 /* freq */ * 16 /* bits */ * 2 /* channels */ * 2 /* seconds */);
|
|
if (err != 0) utilDie("%s", Mix_GetError());
|
|
Mix_AllocateChannels(16);
|
|
|
|
// Start our video playback system
|
|
if (frameFileInit()) utilDie("Unable to initialize framefile handler.");
|
|
if (videoInit()) utilDie("Unable to initialize video player.");
|
|
|
|
// Finish our setup
|
|
SDL_DisableScreenSaver();
|
|
|
|
// Run Singe!
|
|
singe(window, renderer);
|
|
|
|
// Shutdown
|
|
videoQuit();
|
|
frameFileQuit();
|
|
Mix_CloseAudio();
|
|
SDL_DestroyRenderer(renderer);
|
|
SDL_DestroyWindow(window);
|
|
SDL_EnableScreenSaver();
|
|
TTF_Quit();
|
|
IMG_Quit();
|
|
Mix_Quit();
|
|
SDL_Quit();
|
|
if (_confDataDir) free(_confDataDir);
|
|
if (_confVideoFile) free(_confVideoFile);
|
|
if (_confScriptFile) free(_confScriptFile);
|
|
utilTraceEnd();
|
|
ap_free(&parser);
|
|
|
|
#ifdef _WIN32
|
|
if (!_confNoConsole) getchar();
|
|
#endif
|
|
|
|
return 0;
|
|
}
|