430 lines
9.7 KiB
C++
430 lines
9.7 KiB
C++
/*
|
|
* daphne.cpp
|
|
*
|
|
* Copyright (C) 2001 Matt Ownby
|
|
*
|
|
* This file is part of DAPHNE, a laserdisc arcade game emulator
|
|
*
|
|
* DAPHNE 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.
|
|
*
|
|
* DAPHNE 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
// DAPHNE : Dragon's Lair / Space Ace Emulator
|
|
// Started by Matt Ownby, many people have contributed since then
|
|
// Begun August 3rd, 1999
|
|
|
|
// ORIGINAL GOAL (we've obviously done much more than this now hehe):
|
|
|
|
// To emulate the original Dragon's Lair / Space Ace game such that the original ROM's are executed
|
|
// properly, the joystick and buttons are emulated, and the Laserdisc Player is properly
|
|
// controlled
|
|
// In short, so that the original game may be played with the following requirements:
|
|
// - Original Dragon's Lair Laserdisc
|
|
// - Original Dragon's Lair ROM's (disk files, not the physical ROM's heh)
|
|
// - A laserdisc player
|
|
// - A common modern computer (i386 Win32, i386 Linux most likely)
|
|
// No other original hardware (motherboard, power supply, harness) required!
|
|
|
|
#include <string>
|
|
#include "io/my_stdio.h"
|
|
#include <time.h>
|
|
|
|
using namespace std;
|
|
|
|
#ifdef MAC_OSX
|
|
#include "mmxdefs.h"
|
|
#endif
|
|
|
|
#ifndef FREEBSD
|
|
#include <SDL_main.h>
|
|
#else
|
|
#include "/usr/local/include/SDL11/SDL_main.h"
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
// win32 doesn't have regular chdir apparently
|
|
#define chdir _chdir
|
|
#include <direct.h>
|
|
|
|
#endif
|
|
|
|
#ifdef UNIX
|
|
#include <unistd.h> // for chdir
|
|
#endif
|
|
|
|
#include "io/homedir.h"
|
|
#include "io/input.h"
|
|
#include "daphne.h"
|
|
#include "timer/timer.h"
|
|
//#include "io/serial.h"
|
|
#include "sound/sound.h"
|
|
#include "io/conout.h"
|
|
#include "io/conin.h"
|
|
#include "io/cmdline.h"
|
|
#include "io/network.h"
|
|
#include "video/video.h"
|
|
//#include "video/led.h"
|
|
#include "ldp-out/ldp.h"
|
|
#include "video/SDL_Console.h"
|
|
#include "io/error.h"
|
|
//#include "cpu/cpu-debug.h"
|
|
//#include "cpu/cpu.h"
|
|
#include "game/game.h"
|
|
#include "game/singe.h"
|
|
|
|
#include "globals.h"
|
|
// some global data is stored in this file
|
|
|
|
// -------------------------------------------------------------------------------------------------
|
|
|
|
const char *get_daphne_version()
|
|
{
|
|
return "1.0.11";
|
|
}
|
|
|
|
unsigned char get_filename(char *s, unsigned char n)
|
|
// prepares a filename using any wildcards we may have
|
|
// returns filename in s
|
|
// returns 1 if this filename contains wild characters
|
|
// returns 0 if this filename does not contain any wild characters
|
|
{
|
|
|
|
unsigned int i = 0;
|
|
unsigned char result = 0;
|
|
|
|
for (i = 0; i < strlen(s); i++)
|
|
{
|
|
if (s[i] == '+')
|
|
{
|
|
result = 1;
|
|
s[i] = (char) (n + 0x30); // convert wildcard to number
|
|
}
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
void set_quitflag()
|
|
// sets the quit flag
|
|
{
|
|
|
|
quitflag = 1;
|
|
|
|
}
|
|
|
|
unsigned char get_quitflag()
|
|
// returns the quit flag
|
|
{
|
|
|
|
return(quitflag);
|
|
|
|
}
|
|
|
|
bool change_dir(const char *cpszNewDir)
|
|
{
|
|
int i = chdir(cpszNewDir);
|
|
return (i == 0);
|
|
}
|
|
|
|
// sets current directory based on the full path of the executable
|
|
// This solves the problem of someone running daphne without first being in the daphne directory
|
|
void set_cur_dir(const char *exe_loc)
|
|
{
|
|
int index = strlen(exe_loc) - 1; // start on last character
|
|
string path = "";
|
|
|
|
// locate the preceeding / or \ character
|
|
while ((index >= 0) && (exe_loc[index] != '/') && (exe_loc[index] != '\\'))
|
|
{
|
|
index--;
|
|
}
|
|
|
|
// if we found a leading / or \ character
|
|
if (index >= 0)
|
|
{
|
|
path = exe_loc;
|
|
path.erase(index); // erase from here to the end
|
|
change_dir(path.c_str());
|
|
}
|
|
}
|
|
|
|
/////////////////////// MAIN /////////////////////
|
|
|
|
// the main function for both Windows and Linux <grin>
|
|
int main(int argc, char **argv)
|
|
{
|
|
int result_code = 1; // assume an error unless we find otherwise
|
|
|
|
set_cur_dir(argv[0]); // set active directory
|
|
|
|
reset_logfile(argc, argv);
|
|
|
|
// initialize SDL without any subsystems but with the no parachute option so
|
|
// 1 - we can initialize either audio or video first
|
|
// 2 - we can trace segfaults using a debugger
|
|
if (SDL_Init(SDL_INIT_NOPARACHUTE) < 0)
|
|
{
|
|
printerror("Could not initialize SDL!");
|
|
exit(1);
|
|
}
|
|
|
|
// parse the command line (which allocates game and ldp) and continue if no errors
|
|
// this is important! if game_type or ldp_type fails to allocate g_game and g_ldp,
|
|
// then the program will segfault and daphne must NEVER segfault! hehe
|
|
if (parse_cmd_line(argc, argv))
|
|
{
|
|
// MATT : we have to wait until after the command line is parsed before we do anything with the LEDs in case the
|
|
// user does not enable them
|
|
// remember_leds(); // memorizes the status of keyboard leds
|
|
// change_led(false, false, false); // turns all keyboard leds off
|
|
|
|
|
|
// if the display initialized properly
|
|
if (load_bmps() && init_display())
|
|
{
|
|
if (sound_init())
|
|
{
|
|
if (SDL_input_init())
|
|
{
|
|
|
|
// if the video was initialized successfully
|
|
if (g_game->video_init())
|
|
{
|
|
// if the game has some problems, notify the user before the user plays the game
|
|
if (g_game->get_issues())
|
|
{
|
|
printnowookin(g_game->get_issues());
|
|
}
|
|
|
|
SDL_Delay(1000);
|
|
// delay for a bit before the LDP is intialized to make sure
|
|
// all video is done getting drawn before VLDP is initialized
|
|
|
|
// if the laserdisc player was initialized properly
|
|
if (g_ldp->pre_init())
|
|
{
|
|
if (g_game->pre_init()) // initialize all cpu's
|
|
{
|
|
printline("Booting ROM ...");
|
|
g_game->start(); // HERE IS THE MAIN LOOP RIGHT HERE
|
|
g_game->pre_shutdown();
|
|
|
|
// Send our game/ldp type to server to create stats.
|
|
// This was moved to after the game has finished running because it creates a slight delay (like 1 second),
|
|
// which throws off the think_delay function in the LDP class.
|
|
//net_send_data_to_server();
|
|
|
|
result_code = 0; // daphne will exit without any errors
|
|
}
|
|
else
|
|
{
|
|
//exit if returns an error but don't print error message to avoid repetition
|
|
}
|
|
g_ldp->pre_shutdown();
|
|
}
|
|
else
|
|
{
|
|
printerror("Could not initialize laserdisc player!");
|
|
}
|
|
g_game->video_shutdown();
|
|
} // end if game video was initted properly
|
|
else
|
|
{
|
|
printerror("Game-specific video initialization failed!");
|
|
}
|
|
|
|
SDL_input_shutdown();
|
|
}
|
|
else
|
|
{
|
|
printerror("Could not initialize input!");
|
|
}
|
|
sound_shutdown();
|
|
}
|
|
else
|
|
{
|
|
printerror("Sound initialization failed!");
|
|
}
|
|
shutdown_display(); // shut down the display
|
|
} // end init display
|
|
else
|
|
{
|
|
printerror("Video initialization failed!");
|
|
}
|
|
} // end game class allocated properly
|
|
|
|
// if command line was bogus, quit
|
|
else
|
|
{
|
|
char s1[500];
|
|
sprintf(s1,"Bad command line or initialization problem (see daphne_log.txt for details).\n");
|
|
sprintf(s1,"%sTo run SINGE, you must specify which script to run.\n\n",s1);
|
|
sprintf(s1,"%sE,g., singe.exe myscript.singe",s1);
|
|
printerror(s1);
|
|
}
|
|
|
|
// if our g_game class was allocated
|
|
if (g_game)
|
|
{
|
|
delete(g_game);
|
|
}
|
|
|
|
// if g_ldp was allocated, de-allocate it
|
|
if (g_ldp)
|
|
{
|
|
delete(g_ldp);
|
|
}
|
|
|
|
free_bmps(); // always do this no matter what
|
|
|
|
// restore_leds(); // sets keyboard leds back how they were (this is safe even if we have the led's disabled)
|
|
|
|
SDL_Quit();
|
|
exit(result_code);
|
|
|
|
}
|
|
|
|
|
|
// sets the serial port to be used to control LDP
|
|
void set_serial_port(unsigned char i)
|
|
{
|
|
serial_port = i;
|
|
}
|
|
|
|
|
|
unsigned char get_serial_port()
|
|
{
|
|
return(serial_port);
|
|
}
|
|
|
|
void set_baud_rate(int i)
|
|
{
|
|
baud_rate = i;
|
|
}
|
|
|
|
int get_baud_rate()
|
|
{
|
|
return(baud_rate);
|
|
}
|
|
|
|
void set_search_offset(int i)
|
|
{
|
|
search_offset = i;
|
|
}
|
|
|
|
int get_search_offset()
|
|
{
|
|
return(search_offset);
|
|
}
|
|
|
|
unsigned char get_frame_modifier()
|
|
{
|
|
return(frame_modifier);
|
|
}
|
|
|
|
void set_frame_modifier(unsigned char value)
|
|
{
|
|
frame_modifier = value;
|
|
}
|
|
|
|
void set_scoreboard(unsigned char value)
|
|
{
|
|
realscoreboard = value;
|
|
}
|
|
|
|
unsigned char get_scoreboard()
|
|
{
|
|
return (realscoreboard);
|
|
}
|
|
|
|
void set_scoreboard_port(unsigned int value)
|
|
{
|
|
rsb_port = value;
|
|
}
|
|
|
|
unsigned int get_scoreboard_port()
|
|
{
|
|
return(rsb_port);
|
|
}
|
|
|
|
void reset_logfile(int argc, char **argv)
|
|
{
|
|
int i = 0;
|
|
char s[160];
|
|
string str;
|
|
|
|
snprintf(s, sizeof(s), "--DAPHNE version %s", get_daphne_version());
|
|
printline(s);
|
|
str = "--Command line is: ";
|
|
for (i = 0; i < argc; i++)
|
|
{
|
|
str = str + argv[i] + " ";
|
|
}
|
|
printline(str.c_str());
|
|
snprintf(s, sizeof(s), "--CPU : %s %d MHz || Mem : %d megs", get_cpu_name(), get_cpu_mhz(), get_sys_mem());
|
|
printline(s);
|
|
snprintf(s, sizeof(s), "--OS : %s || Video : %s", get_os_description(), get_video_description());
|
|
printline(s);
|
|
outstr("--OpenGL: ");
|
|
#ifdef USE_OPENGL
|
|
printline("Compiled In");
|
|
#else
|
|
printline("Not Compiled In");
|
|
#endif // USE_OPENGL
|
|
|
|
outstr("--RGB2YUV Function: ");
|
|
#ifdef USE_MMX
|
|
printline("MMX");
|
|
#else
|
|
printline("C");
|
|
#endif
|
|
outstr("--Line Blending Function: ");
|
|
#ifdef USE_MMX
|
|
printline("MMX");
|
|
#else
|
|
printline("C");
|
|
#endif // blend MMX
|
|
|
|
outstr("--Audio Mixing Function: ");
|
|
#ifdef USE_MMX
|
|
printline("MMX");
|
|
#else
|
|
printline("C");
|
|
#endif // blend MMX
|
|
}
|
|
|
|
// added by JFA for -idleexit
|
|
void set_idleexit(unsigned int value)
|
|
{
|
|
idleexit = value;
|
|
}
|
|
|
|
unsigned int get_idleexit()
|
|
{
|
|
return(idleexit);
|
|
}
|
|
// end edit
|
|
|
|
// added by JFA for -startsilent
|
|
void set_startsilent(unsigned char value)
|
|
{
|
|
startsilent = value;
|
|
}
|
|
|
|
unsigned char get_startsilent()
|
|
{
|
|
return(startsilent);
|
|
}
|
|
// end edit
|