mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 05:45:38 +00:00
- Program settings are now managed by the CConfig class.
- Moved Logger.h to OSD/, cleaned up comments. - Command line and config file parsing have been rewritten. - Began replacing C standard library headers with C++ versions (eg. stdio.h -> cstdio). I think I got most of them, but not all.
This commit is contained in:
parent
5e1ea75374
commit
d318efe58c
|
@ -156,7 +156,7 @@ endif
|
|||
# Objects and Dependencies
|
||||
#
|
||||
HEADERS = Src/Supermodel.h Src/OSD/SDL/Types.h
|
||||
OBJ = $(OBJ_DIR)/PPCDisasm.obj $(OBJ_DIR)/Games.obj $(OBJ_DIR)/INIFile.obj $(OBJ_DIR)/BlockFile.obj $(OBJ_DIR)/93C46.obj \
|
||||
OBJ = $(OBJ_DIR)/PPCDisasm.obj $(OBJ_DIR)/Games.obj $(OBJ_DIR)/Config.obj $(OBJ_DIR)/INIFile.obj $(OBJ_DIR)/BlockFile.obj $(OBJ_DIR)/93C46.obj \
|
||||
$(OBJ_DIR)/ROMLoad.obj $(OBJ_DIR)/unzip.obj $(OBJ_DIR)/ioapi.obj $(OBJ_DIR)/Error.obj $(OBJ_DIR)/glew.obj $(OBJ_DIR)/Shader.obj \
|
||||
$(OBJ_DIR)/Real3D.obj $(OBJ_DIR)/Render3D.obj $(OBJ_DIR)/Models.obj $(OBJ_DIR)/Render2D.obj $(OBJ_DIR)/TileGen.obj \
|
||||
$(OBJ_DIR)/Model3.obj $(OBJ_DIR)/ppc.obj $(OBJ_DIR)/Main.obj $(OBJ_DIR)/Audio.obj $(OBJ_DIR)/Thread.obj $(OBJ_DIR)/SoundBoard.obj \
|
||||
|
|
31
Src/Config.cpp
Normal file
31
Src/Config.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011 Bart Trzynadlowski
|
||||
**
|
||||
** This file is part of Supermodel.
|
||||
**
|
||||
** Supermodel 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 3 of the License, or (at your option)
|
||||
** any later version.
|
||||
**
|
||||
** Supermodel 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 Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
/*
|
||||
* Config.cpp
|
||||
*
|
||||
* Program-wide configuration settings.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
|
||||
CConfig g_Config;
|
71
Src/Config.h
Normal file
71
Src/Config.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011 Bart Trzynadlowski
|
||||
**
|
||||
** This file is part of Supermodel.
|
||||
**
|
||||
** Supermodel 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 3 of the License, or (at your option)
|
||||
** any later version.
|
||||
**
|
||||
** Supermodel 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 Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
/*
|
||||
* Config.h
|
||||
*
|
||||
* Header file for program-wide configuration settings.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_CONFIG_H
|
||||
#define INCLUDED_CONFIG_H
|
||||
|
||||
|
||||
#include "Supermodel.h"
|
||||
|
||||
|
||||
/*
|
||||
* CConfig:
|
||||
*
|
||||
* Class defining all configuration settings. Inherits settings from classes
|
||||
* defined throughout the program.
|
||||
*
|
||||
* Conventions
|
||||
* -----------
|
||||
* - Modules and classes should only use the members of their own configuration
|
||||
* class, so long as this is practical. This is left to programmer
|
||||
* discretion. The intent is that one class, CReal3D for example, should not
|
||||
* need information from another unrelated class, CModel3, unless explicitly
|
||||
* passed to it. On the other hand, the OSD layer may have a legitimate
|
||||
* need to use the renderer's video settings rather than maintaining its own.
|
||||
* - Member variables that have a limited range of allowable values must be
|
||||
* private and accessed through accessor members (SetVar(), GetVar()). The
|
||||
* accessors must ensure that a value outside the allowable range is never
|
||||
* returned and must clamp or reset to a default when an invalid setting
|
||||
* is passed. Warnings may be printed.
|
||||
* - Strings should be copied and retained locally.
|
||||
* - Constructors must be defined and must initialize to the program default.
|
||||
* - User-tunable settings should be stored here, not necessarily every
|
||||
* concievable parameter a class initializer might take.
|
||||
*/
|
||||
class CConfig: public COSDConfig, public CRender3DConfig, public CModel3Config, public CSoundBoardConfig, public CDSBConfig
|
||||
{
|
||||
};
|
||||
|
||||
/*
|
||||
* g_Config:
|
||||
*
|
||||
* Program-wide configuration settings object.
|
||||
*/
|
||||
extern CConfig g_Config;
|
||||
|
||||
|
||||
#endif // INCLUDED_CONFIG_H
|
|
@ -1283,7 +1283,7 @@ void CRender3D::SetStep(int stepID)
|
|||
DebugLog("Render3D set to Step %d.%d\n", (step>>4)&0xF, step&0xF);
|
||||
}
|
||||
|
||||
BOOL CRender3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, const char *vsFile, const char *fsFile)
|
||||
BOOL CRender3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes)
|
||||
{
|
||||
// Allocate memory for texture buffer
|
||||
textureBuffer = new(std::nothrow) GLfloat[512*512*4];
|
||||
|
@ -1331,6 +1331,8 @@ BOOL CRender3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned
|
|||
yOffs = yOffset;
|
||||
|
||||
// Load shaders
|
||||
const char *vsFile = g_Config.vertexShaderFile.size() ? g_Config.vertexShaderFile.c_str() : NULL;
|
||||
const char *fsFile = g_Config.fragmentShaderFile.size() ? g_Config.fragmentShaderFile.c_str() : NULL;
|
||||
if (OKAY != LoadShaderProgram(&shaderProgram,&vertexShader,&fragmentShader,vsFile,fsFile,vertexShaderSource,fragmentShaderSource))
|
||||
return FAIL;
|
||||
|
||||
|
|
|
@ -163,9 +163,27 @@ struct ModelCache
|
|||
|
||||
|
||||
/******************************************************************************
|
||||
CRender3D Class Definition
|
||||
CRender3D Classes
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* CRender3DConfig:
|
||||
*
|
||||
* Settings used by CRender3D.
|
||||
*/
|
||||
class CRender3DConfig
|
||||
{
|
||||
public:
|
||||
string vertexShaderFile; // path to vertex shader or "" to use internal shader
|
||||
string fragmentShaderFile; // fragment shader
|
||||
|
||||
// Defaults
|
||||
CRender3DConfig(void)
|
||||
{
|
||||
// nothing to do, strings will be clear to begin with
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* CRender3D:
|
||||
*
|
||||
|
@ -244,30 +262,27 @@ public:
|
|||
void SetStep(int stepID);
|
||||
|
||||
/*
|
||||
* Init(xOffset, yOffset, xRes, yRes, vsFile, fsFile):
|
||||
* Init(xOffset, yOffset, xRes, yRes):
|
||||
*
|
||||
* One-time initialization of the context. Must be called before any other
|
||||
* members (meaning it should be called even before being attached to any
|
||||
* other objects that want to use it).
|
||||
*
|
||||
* External shader files are loaded according to configuration settings.
|
||||
*
|
||||
* Parameters:
|
||||
* xOffset X offset of display surface in pixels (in case resolution
|
||||
* is smaller than the true display surface).
|
||||
* yOffset Y offset.
|
||||
* xRes Horizontal resolution of display surface in pixels.
|
||||
* yRes Vertical resolution.
|
||||
* vsFile External vertex shader path. If NULL, the internal
|
||||
* shader is used.
|
||||
* fsFile External fragment shader path. If NULL, the internal
|
||||
* shader is used.
|
||||
*
|
||||
* Returns:
|
||||
* OKAY is successful, otherwise FAILED if a non-recoverable error
|
||||
* occurred. Any allocated memory will not be freed until the
|
||||
* destructor is called. Prints own error messages.
|
||||
*/
|
||||
BOOL Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes,
|
||||
const char *vsFile, const char *fsFile);
|
||||
BOOL Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes);
|
||||
|
||||
/*
|
||||
* CRender3D(void):
|
||||
|
|
|
@ -26,10 +26,8 @@
|
|||
*
|
||||
* To-Do List
|
||||
* ----------
|
||||
* - Allow default section name to be set at any time. To support this, must
|
||||
* allow for multiple sections with the same name to co-exist. The search
|
||||
* procedure must look through all sections rather than stopping at the
|
||||
* first section match. This is easy enough to add.
|
||||
* - Add an iterator to retrieve all settings associated with a given section.
|
||||
* This will allow detection of invalid setting names, if the caller desires.
|
||||
* - Add boolean on/off, true/false keywords.
|
||||
* - Note that linePtr does not necessarily correspond to actual lines in the
|
||||
* file (newlines should be counted by the tokenizer for that).
|
||||
|
|
|
@ -63,7 +63,8 @@ public:
|
|||
*
|
||||
* Returns:
|
||||
* OKAY if the setting was found, FAIL otherwise. The type is not
|
||||
* checked.
|
||||
* checked. If the setting is not found, the output parameter will not
|
||||
* be modified.
|
||||
*/
|
||||
BOOL Get(string SectionName, string SettingName, int& value);
|
||||
BOOL Get(string SectionName, string SettingName, unsigned& value);
|
||||
|
|
45
Src/Logger.h
45
Src/Logger.h
|
@ -1,45 +0,0 @@
|
|||
#ifndef INCLUDED_LOGGER_H
|
||||
#define INCLUDED_LOGGER_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/*
|
||||
* CLogger
|
||||
*
|
||||
* Abstract class that receives log messages from Supermodel.
|
||||
*/
|
||||
class CLogger
|
||||
{
|
||||
public:
|
||||
void DebugLog(const char *fmt, ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
DebugLog(fmt, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
void InfoLog(const char *fmt, ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
InfoLog(fmt, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
void ErrorLog(const char *fmt, ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
ErrorLog(fmt, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
virtual void DebugLog(const char *fmt, va_list vl) = 0;
|
||||
|
||||
virtual void InfoLog(const char *fmt, va_list vl) = 0;
|
||||
|
||||
virtual void ErrorLog(const char *fmt, va_list vl) = 0;
|
||||
};
|
||||
|
||||
#endif // INCLUDED_LOGGER_H
|
|
@ -139,8 +139,14 @@ int CDSBResampler::UpSampleAndMix(INT16 *outL, INT16 *outR, INT16 *inL, INT16 *i
|
|||
int delta = (inRate<<8)/outRate; // (1/fout)/(1/fin)=fin/fout, 24.8 fixed point
|
||||
int outIdx = 0;
|
||||
int inIdx = 0;
|
||||
INT16 leftSample, rightSample;
|
||||
INT16 v[2];
|
||||
INT32 leftSample, rightSample, leftSoundSample, rightSoundSample;
|
||||
INT32 v[2], musicVol, soundVol;
|
||||
|
||||
// Obtain program volume settings and convert to 24.8 fixed point (0-200 -> 0x00-0x200)
|
||||
musicVol = g_Config.GetMusicVolume();
|
||||
soundVol = g_Config.GetSoundVolume();
|
||||
musicVol = (INT32) ((float) 0x100 * (float) musicVol / 100.0f);
|
||||
soundVol = (INT32) ((float) 0x100 * (float) soundVol / 100.0f);
|
||||
|
||||
// Scale volume from 0x00-0xFF -> 0x00-0x100 (24.8 fixed point)
|
||||
v[0] = (INT16) ((float) 0x100 * (float) volumeL / 255.0f);
|
||||
|
@ -153,13 +159,17 @@ int CDSBResampler::UpSampleAndMix(INT16 *outL, INT16 *outR, INT16 *inL, INT16 *i
|
|||
leftSample = ((int)inL[inIdx]*pFrac+(int)inL[inIdx+1]*nFrac) >> 8; // left channel
|
||||
rightSample = ((int)inR[inIdx]*pFrac+(int)inR[inIdx+1]*nFrac) >> 8; // right channel
|
||||
|
||||
// Apply volume
|
||||
leftSample = (leftSample*v[0]) >> 8;
|
||||
rightSample = (rightSample*v[0]) >> 8;
|
||||
// Apply DSB volume and then overall music volume setting
|
||||
leftSample = (leftSample*v[0]*musicVol) >> 16; // multiplied by two 24.8 numbers, shift back by 16
|
||||
rightSample = (rightSample*v[0]*musicVol) >> 16;
|
||||
|
||||
// Apply sound volume setting
|
||||
leftSoundSample = (outL[outIdx]*soundVol) >> 8;
|
||||
rightSoundSample = (outR[outIdx]*soundVol) >> 8;
|
||||
|
||||
// Mix and output
|
||||
outL[outIdx] = MixAndClip(outL[outIdx], leftSample);
|
||||
outR[outIdx] = MixAndClip(outR[outIdx], rightSample);
|
||||
outL[outIdx] = MixAndClip(leftSoundSample, leftSample);
|
||||
outR[outIdx] = MixAndClip(rightSoundSample, rightSample);
|
||||
outIdx++;
|
||||
|
||||
// Time step
|
||||
|
@ -413,6 +423,15 @@ void CDSB1::RunFrame(INT16 *audioL, INT16 *audioR)
|
|||
int cycles;
|
||||
UINT8 v;
|
||||
|
||||
if (!g_Config.emulateDSB)
|
||||
{
|
||||
// DSB code applies SCSP volume, too, so we must still mix
|
||||
memset(mpegL, 0, (32000/60+2)*sizeof(INT16));
|
||||
memset(mpegR, 0, (32000/60+2)*sizeof(INT16));
|
||||
retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, mpegL, mpegR, 0, 0, 44100/60, 32000/60+2, 44100, 32000);
|
||||
return;
|
||||
}
|
||||
|
||||
// While FIFO not empty, fire interrupts, run for up to one frame
|
||||
for (cycles = (4000000/60)/4; (cycles > 0) && (fifoIdxR != fifoIdxW); )
|
||||
{
|
||||
|
@ -948,6 +967,15 @@ void CDSB2::SendCommand(UINT8 data)
|
|||
void CDSB2::RunFrame(INT16 *audioL, INT16 *audioR)
|
||||
{
|
||||
#ifdef SUPERMODEL_SOUND
|
||||
if (!g_Config.emulateDSB)
|
||||
{
|
||||
// DSB code applies SCSP volume, too, so we must still mix
|
||||
memset(mpegL, 0, (32000/60+2)*sizeof(INT16));
|
||||
memset(mpegR, 0, (32000/60+2)*sizeof(INT16));
|
||||
retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, mpegL, mpegR, volume[0], volume[1], 44100/60, 32000/60+2, 44100, 32000);
|
||||
return;
|
||||
}
|
||||
|
||||
M68KSetContext(&M68K);
|
||||
//printf("DSB2 run frame PC=%06X\n", M68KGetPC());
|
||||
|
||||
|
|
|
@ -35,6 +35,71 @@
|
|||
#include "CPU/Bus.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Configuration
|
||||
|
||||
Because DSB code mixes both the sound board SCSP and MPEG audio together, both
|
||||
volume settings are stored here (for now).
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* CDSBConfig:
|
||||
*
|
||||
* Settings used by CDSB.
|
||||
*/
|
||||
class CDSBConfig
|
||||
{
|
||||
public:
|
||||
bool emulateDSB; // DSB emulation (enabled if TRUE)
|
||||
|
||||
// Sound (SCSP) volume (0-200, 100 being full amplitude)
|
||||
inline void SetSoundVolume(unsigned vol)
|
||||
{
|
||||
if (vol > 200)
|
||||
{
|
||||
ErrorLog("Sound volume cannot exceed 200%%; setting to 100%%.\n");
|
||||
vol = 100;
|
||||
}
|
||||
|
||||
soundVol = vol;
|
||||
}
|
||||
|
||||
inline unsigned GetSoundVolume(void)
|
||||
{
|
||||
return soundVol;
|
||||
}
|
||||
|
||||
// Music (DSB MPEG) volume (0-200)
|
||||
inline void SetMusicVolume(unsigned vol)
|
||||
{
|
||||
if (vol > 200)
|
||||
{
|
||||
ErrorLog("Music volume cannot exceed 200%%; setting to 100%%.\n");
|
||||
vol = 100;
|
||||
}
|
||||
|
||||
musicVol = vol;
|
||||
}
|
||||
|
||||
inline unsigned GetMusicVolume(void)
|
||||
{
|
||||
return musicVol;
|
||||
}
|
||||
|
||||
// Defaults
|
||||
CDSBConfig(void)
|
||||
{
|
||||
emulateDSB = true;
|
||||
soundVol = 100;
|
||||
musicVol = 100;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned soundVol;
|
||||
unsigned musicVol;
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Resampling
|
||||
|
||||
|
|
|
@ -184,9 +184,9 @@
|
|||
*/
|
||||
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include "Supermodel.h"
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -1870,7 +1870,7 @@ void CModel3::ClearNVRAM(void)
|
|||
void CModel3::RunFrame(void)
|
||||
{
|
||||
// See if currently running multi-threaded
|
||||
if (multiThreaded)
|
||||
if (g_Config.multiThreaded)
|
||||
{
|
||||
// If so, check all threads are up and running
|
||||
if (!StartThreads())
|
||||
|
@ -1924,7 +1924,7 @@ void CModel3::RunFrame(void)
|
|||
|
||||
ThreadError:
|
||||
ErrorLog("Threading error in CModel3::RunFrame: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
|
||||
multiThreaded = false;
|
||||
g_Config.multiThreaded = false;
|
||||
}
|
||||
|
||||
bool CModel3::StartThreads()
|
||||
|
@ -1966,7 +1966,7 @@ bool CModel3::StartThreads()
|
|||
ThreadError:
|
||||
ErrorLog("Unable to create threads and/or synchronization objects: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
|
||||
DeleteThreadObjects();
|
||||
multiThreaded = false;
|
||||
g_Config.multiThreaded = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2066,7 +2066,7 @@ void CModel3::RunSoundBoardThread()
|
|||
|
||||
ThreadError:
|
||||
ErrorLog("Threading error in sound board thread: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
|
||||
multiThreaded = false;
|
||||
g_Config.multiThreaded = false;
|
||||
}
|
||||
|
||||
#ifdef SUPERMODEL_DRIVEBOARD
|
||||
|
@ -2097,14 +2097,14 @@ void CModel3::RunDriveBoardThread()
|
|||
|
||||
ThreadError:
|
||||
ErrorLog("Threading error in drive board thread: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
|
||||
multiThreaded = false;
|
||||
g_Config.multiThreaded = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CModel3::RunMainBoardFrame(void)
|
||||
{
|
||||
// Run the PowerPC for a frame
|
||||
ppc_execute(ppcFrequency/60-10000);
|
||||
ppc_execute(g_Config.GetPowerPCFrequency()*1000000/60-10000);
|
||||
//printf("PC=%08X LR=%08X\n", ppc_get_pc(), ppc_get_lr());
|
||||
|
||||
// VBlank
|
||||
|
@ -2612,16 +2612,10 @@ void CModel3::AttachInputs(CInputs *InputsPtr)
|
|||
}
|
||||
|
||||
// Model 3 initialization. Some initialization is deferred until ROMs are loaded in LoadROMSet()
|
||||
BOOL CModel3::Init(unsigned ppcFrequencyParam, BOOL multiThreadedParam)
|
||||
BOOL CModel3::Init(void)
|
||||
{
|
||||
float memSizeMB = (float)MEMORY_POOL_SIZE/(float)0x100000;
|
||||
|
||||
// PowerPC frequency
|
||||
ppcFrequency = ppcFrequencyParam;
|
||||
if (ppcFrequency < 1000000)
|
||||
ppcFrequency = 1000000;
|
||||
multiThreaded = !!multiThreadedParam;
|
||||
|
||||
// Allocate all memory for ROMs and PPC RAM
|
||||
memoryPool = new(std::nothrow) UINT8[MEMORY_POOL_SIZE];
|
||||
if (NULL == memoryPool)
|
||||
|
@ -2689,7 +2683,7 @@ CModel3::CModel3(void)
|
|||
|
||||
securityPtr = 0;
|
||||
|
||||
multiThreaded = true;
|
||||
g_Config.multiThreaded = true;
|
||||
startedThreads = false;
|
||||
sndBrdThread = NULL;
|
||||
#ifdef SUPERMODEL_DRIVEBOARD
|
||||
|
|
|
@ -22,12 +22,48 @@
|
|||
/*
|
||||
* Model3.h
|
||||
*
|
||||
* Header file defining the CModel3 and CModel3Inputs classes.
|
||||
* Header file defining the CModel3, CModel3Config, and CModel3Inputs classes.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_MODEL3_H
|
||||
#define INCLUDED_MODEL3_H
|
||||
|
||||
/*
|
||||
* CModel3Config:
|
||||
*
|
||||
* Settings used by CModel3.
|
||||
*/
|
||||
class CModel3Config
|
||||
{
|
||||
public:
|
||||
bool multiThreaded; // Multi-threading (enabled if TRUE)
|
||||
|
||||
// PowerPC clock frequency in MHz (minimum: 1 MHz)
|
||||
inline void SetPowerPCFrequency(unsigned f)
|
||||
{
|
||||
if ((f<1) || (f>1000))
|
||||
{
|
||||
ErrorLog("PowerPC frequency must be between 1 and 1000 MHz; setting to 40 MHz.");
|
||||
f = 40;
|
||||
}
|
||||
ppcFrequency = f*1000000;
|
||||
}
|
||||
inline unsigned GetPowerPCFrequency(void)
|
||||
{
|
||||
return ppcFrequency/1000000;
|
||||
}
|
||||
|
||||
// Defaults
|
||||
CModel3Config(void)
|
||||
{
|
||||
multiThreaded = false; // disable by default
|
||||
ppcFrequency = 40*1000000; // 40 MHz
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned ppcFrequency; // in Hz
|
||||
};
|
||||
|
||||
/*
|
||||
* CModel3:
|
||||
*
|
||||
|
@ -228,20 +264,16 @@ public:
|
|||
void AttachInputs(CInputs *InputsPtr);
|
||||
|
||||
/*
|
||||
* Init(ppcFrequencyParam, multiThreadedParam):
|
||||
* Init(void):
|
||||
*
|
||||
* One-time initialization of the context. Must be called prior to all
|
||||
* other members. Allocates memory and initializes device states.
|
||||
*
|
||||
* Parameters:
|
||||
* ppcFrequencyParam PowerPC frequency in Hz. If less than 1 MHz,
|
||||
* will be clamped to 1 MHz.
|
||||
*
|
||||
* Returns:
|
||||
* OKAY is successful, otherwise FAILED if a non-recoverable error
|
||||
* occurred. Prints own error messages.
|
||||
*/
|
||||
BOOL Init(unsigned ppcFrequencyParam, BOOL multiThreadedParam);
|
||||
BOOL Init(void);
|
||||
|
||||
/*
|
||||
* CModel3(void):
|
||||
|
@ -321,10 +353,8 @@ private:
|
|||
|
||||
// PowerPC
|
||||
PPC_FETCH_REGION PPCFetchRegions[3];
|
||||
unsigned ppcFrequency; // clock frequency (Hz)
|
||||
|
||||
// Multiple threading
|
||||
bool multiThreaded; // True if should run CPUs in multiple threads, otherwise everything is run in a single thread
|
||||
bool startedThreads; // True if threads have been created and started
|
||||
CThread *sndBrdThread; // Sound board thread
|
||||
#ifdef SUPERMODEL_DRIVEBOARD
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
#include "Supermodel.h"
|
||||
|
||||
// DEBUG
|
||||
//#define SUPERMODEL_LOG_AUDIO // define this to log all audio to sound.bin
|
||||
#define SUPERMODEL_LOG_AUDIO // define this to log all audio to sound.bin
|
||||
#ifdef SUPERMODEL_LOG_AUDIO
|
||||
static FILE *soundFP;
|
||||
#endif
|
||||
|
@ -362,10 +362,17 @@ void CSoundBoard::RunFrame(void)
|
|||
{
|
||||
#ifdef SUPERMODEL_SOUND
|
||||
// Run sound board first to generate SCSP audio
|
||||
M68KSetContext(&M68K);
|
||||
SCSP_Update();
|
||||
M68KGetContext(&M68K);
|
||||
//memset(audioL, 0, 44100/60*sizeof(INT16));memset(audioR, 0, 44100/60*sizeof(INT16)); // clear, I want DSB only
|
||||
if (g_Config.emulateSCSP)
|
||||
{
|
||||
M68KSetContext(&M68K);
|
||||
SCSP_Update();
|
||||
M68KGetContext(&M68K);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(audioL, 0, 44100/60*sizeof(INT16));
|
||||
memset(audioR, 0, 44100/60*sizeof(INT16));
|
||||
}
|
||||
|
||||
// Run DSB and mix with existing audio
|
||||
if (NULL != DSB)
|
||||
|
|
|
@ -32,6 +32,23 @@
|
|||
#include "CPU/Bus.h"
|
||||
#include "Model3/DSB.h"
|
||||
|
||||
/*
|
||||
* CSoundBoardConfig:
|
||||
*
|
||||
* Settings used by CSoundBoard.
|
||||
*/
|
||||
class CSoundBoardConfig
|
||||
{
|
||||
public:
|
||||
bool emulateSCSP; // SCSP emulation (enabled if TRUE)
|
||||
|
||||
// Defaults
|
||||
CSoundBoardConfig(void)
|
||||
{
|
||||
emulateSCSP = true;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* CSoundBoard:
|
||||
*
|
||||
|
|
286
Src/OSD/Logger.h
Normal file
286
Src/OSD/Logger.h
Normal file
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* Logger.h
|
||||
*
|
||||
* Header file for message logging. The OSD code is expected to set up a
|
||||
* default logger (CFileLogger).
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_LOGGER_H
|
||||
#define INCLUDED_LOGGER_H
|
||||
|
||||
#include "Types.h"
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Class Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* CLogger
|
||||
*
|
||||
* Abstract class that receives log messages from Supermodel's log functions.
|
||||
* The logger object handles actual output of messages. Use the function-based
|
||||
* message logging interface to generate messages.
|
||||
*/
|
||||
class CLogger
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* DebugLog(fmt, ...):
|
||||
* DebugLog(fmt, vl):
|
||||
*
|
||||
* Prints to debug log. If DEBUG is not defined, will end up doing nothing.
|
||||
*
|
||||
* Parameters:
|
||||
* fmt printf()-style format string.
|
||||
* ... Variable number of parameters, corresponding to format
|
||||
* string.
|
||||
* vl Variable arguments already stored in a list.
|
||||
*/
|
||||
void DebugLog(const char *fmt, ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
DebugLog(fmt, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
virtual void DebugLog(const char *fmt, va_list vl) = 0;
|
||||
|
||||
/*
|
||||
* InfoLog(fmt, ...):
|
||||
* InfoLog(fmt, vl):
|
||||
*
|
||||
* Prints to error log but does not output an error to stderr. This is
|
||||
* useful for printing session information to the error log.
|
||||
*
|
||||
* Parameters:
|
||||
* fmt printf()-style format string.
|
||||
* ... Variable number of parameters, corresponding to format
|
||||
* string.
|
||||
* vl Variable arguments already stored in a list.
|
||||
*/
|
||||
void InfoLog(const char *fmt, ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
InfoLog(fmt, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
virtual void InfoLog(const char *fmt, va_list vl) = 0;
|
||||
|
||||
/*
|
||||
* ErrorLog(fmt, ...):
|
||||
* ErrorLog(fmt, vl):
|
||||
*
|
||||
* Prints to error log and outputs an error message to stderr.
|
||||
*
|
||||
* Parameters:
|
||||
* fmt printf()-style format string.
|
||||
* ... Variable number of parameters, corresponding to format
|
||||
* string.
|
||||
* vl Variable arguments already stored in a list.
|
||||
*/
|
||||
void ErrorLog(const char *fmt, ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
ErrorLog(fmt, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
virtual void ErrorLog(const char *fmt, va_list vl) = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
* CFileLogger:
|
||||
*
|
||||
* Default logger that logs to debug and error log files. Files are opened and
|
||||
* closed for each message in order to preserve contents in case of program
|
||||
* crash.
|
||||
*/
|
||||
class CFileLogger : public CLogger
|
||||
{
|
||||
public:
|
||||
|
||||
void DebugLog(const char *fmt, va_list vl)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
char string[1024];
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(m_debugLogFile, "ab");
|
||||
if (NULL != fp)
|
||||
{
|
||||
vsprintf(string, fmt, vl);
|
||||
fprintf(fp, string);
|
||||
fclose(fp);
|
||||
}
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
void InfoLog(const char *fmt, va_list vl)
|
||||
{
|
||||
char string[4096];
|
||||
FILE *fp;
|
||||
|
||||
vsprintf(string, fmt, vl);
|
||||
|
||||
fp = fopen(m_errorLogFile, "ab");
|
||||
if (NULL != fp)
|
||||
{
|
||||
fprintf(fp, "%s\n", string);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
CLogger::DebugLog("Info: ");
|
||||
CLogger::DebugLog(string);
|
||||
CLogger::DebugLog("\n");
|
||||
}
|
||||
|
||||
void ErrorLog(const char *fmt, va_list vl)
|
||||
{
|
||||
char string[4096];
|
||||
FILE *fp;
|
||||
|
||||
vsprintf(string, fmt, vl);
|
||||
fprintf(stderr, "Error: %s\n", string);
|
||||
|
||||
fp = fopen(m_errorLogFile, "ab");
|
||||
if (NULL != fp)
|
||||
{
|
||||
fprintf(fp, "%s\n", string);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
CLogger::DebugLog("Error: ");
|
||||
CLogger::DebugLog(string);
|
||||
CLogger::DebugLog("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* ClearLogs():
|
||||
*
|
||||
* Clears all log files.
|
||||
*/
|
||||
void ClearLogs(void)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
ClearLog(m_debugLogFile, "Supermodel v"SUPERMODEL_VERSION" Debug Log");
|
||||
#endif // DEBUG
|
||||
ClearLog(m_errorLogFile, "Supermodel v"SUPERMODEL_VERSION" Error Log");
|
||||
}
|
||||
|
||||
/*
|
||||
* ClearLog(file, title):
|
||||
*
|
||||
* Clears a log file.
|
||||
*
|
||||
* Parameters:
|
||||
* file File name.
|
||||
* title A string that is written to the file after it is cleared.
|
||||
*/
|
||||
void ClearLog(const char *file, const char *title)
|
||||
{
|
||||
FILE *fp = fopen(file, "w");
|
||||
if (NULL != fp)
|
||||
{
|
||||
unsigned i;
|
||||
fprintf(fp, "%s\n", title);
|
||||
for (i = 0; i < strlen(title); i++)
|
||||
fputc('-', fp);
|
||||
fprintf(fp, "\n\n");
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CFileLogger(debugLogFile, errorLogFile):
|
||||
*
|
||||
* Constructor. Specifies debug and error log files to use.
|
||||
*/
|
||||
CFileLogger(const char *debugLogFile, const char *errorLogFile) :
|
||||
m_debugLogFile(debugLogFile), m_errorLogFile(errorLogFile)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
const char *m_debugLogFile;
|
||||
const char *m_errorLogFile;
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Log Functions
|
||||
|
||||
Message logging interface. All messages are passed by the OSD layer to the
|
||||
currently active logger object.
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* DebugLog(fmt, ...):
|
||||
*
|
||||
* Prints debugging information. The OSD layer may choose to print this to a
|
||||
* log file, the screen, neither, or both. Newlines and other formatting codes
|
||||
* must be explicitly included.
|
||||
*
|
||||
* Parameters:
|
||||
* fmt A format string (the same as printf()).
|
||||
* ... Variable number of arguments, as required by format string.
|
||||
*/
|
||||
extern void DebugLog(const char *fmt, ...);
|
||||
|
||||
/*
|
||||
* ErrorLog(fmt, ...):
|
||||
*
|
||||
* Prints error information. Errors need not require program termination and
|
||||
* may simply be informative warnings to the user. Newlines should not be
|
||||
* included in the format string -- they are automatically added at the end of
|
||||
* a line.
|
||||
*
|
||||
* Parameters:
|
||||
* fmt A format string (the same as printf()).
|
||||
* ... Variable number of arguments, as required by format string.
|
||||
*
|
||||
* Returns:
|
||||
* Must always return FAIL.
|
||||
*/
|
||||
extern BOOL ErrorLog(const char *fmt, ...);
|
||||
|
||||
/*
|
||||
* InfoLog(fmt, ...);
|
||||
*
|
||||
* Prints information to the error log file but does not print to stderr. This
|
||||
* is useful for logging non-error information. Newlines are automatically
|
||||
* appended.
|
||||
*
|
||||
* Parameters:
|
||||
* fmt Format string (same as printf()).
|
||||
* ... Variable number of arguments as required by format string.
|
||||
*/
|
||||
extern void InfoLog(const char *fmt, ...);
|
||||
|
||||
/*
|
||||
* SetLogger(Logger):
|
||||
*
|
||||
* Sets the logger object to use.
|
||||
*
|
||||
* Parameters:
|
||||
* Logger New logger object. If NULL, log messages will not be output.
|
||||
*/
|
||||
extern void SetLogger(CLogger *Logger);
|
||||
|
||||
/*
|
||||
* GetLogger(void):
|
||||
*
|
||||
* Returns:
|
||||
* Current logger object (NULL if none has been set).
|
||||
*/
|
||||
extern CLogger *GetLogger(void);
|
||||
|
||||
|
||||
#endif // INCLUDED_LOGGER_H
|
|
@ -40,10 +40,10 @@
|
|||
*/
|
||||
|
||||
#include <new>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstdarg>
|
||||
#include "Pkgs/glew.h"
|
||||
#ifdef SUPERMODEL_OSX
|
||||
#include <SDL/SDL.h>
|
||||
|
@ -57,15 +57,69 @@
|
|||
#include "DirectInputSystem.h"
|
||||
#endif
|
||||
|
||||
CLogger *GetLogger();
|
||||
void SetLogger(CLogger *logger);
|
||||
|
||||
/******************************************************************************
|
||||
Error and Debug Logging
|
||||
******************************************************************************/
|
||||
|
||||
// Log file names
|
||||
#define DEBUG_LOG_FILE "debug.log"
|
||||
#define ERROR_LOG_FILE "error.log"
|
||||
|
||||
// Logger object is used to redirect log messages appropriately
|
||||
static CLogger *s_Logger = NULL;
|
||||
|
||||
CLogger *GetLogger()
|
||||
{
|
||||
return s_Logger;
|
||||
}
|
||||
|
||||
void SetLogger(CLogger *Logger)
|
||||
{
|
||||
s_Logger = Logger;
|
||||
}
|
||||
|
||||
void DebugLog(const char *fmt, ...)
|
||||
{
|
||||
if (s_Logger == NULL)
|
||||
return;
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
s_Logger->DebugLog(fmt, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
void InfoLog(const char *fmt, ...)
|
||||
{
|
||||
if (s_Logger == NULL)
|
||||
return;
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
s_Logger->InfoLog(fmt, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
BOOL ErrorLog(const char *fmt, ...)
|
||||
{
|
||||
if (s_Logger == NULL)
|
||||
return FAIL;
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
s_Logger->ErrorLog(fmt, vl);
|
||||
va_end(vl);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Display Management
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* Position and size of rectangular region within OpenGL display to render to
|
||||
* Position and size of rectangular region within OpenGL display to render to.
|
||||
* Unlike the g_Config object, these end up containing the actual resolution
|
||||
* (and computed offsets within the viewport) that will be rendered based on
|
||||
* what was obtained from SDL.
|
||||
*/
|
||||
unsigned xOffset, yOffset; // offset of renderer output within OpenGL viewport
|
||||
unsigned xRes, yRes; // renderer output resolution (can be smaller than GL viewport)
|
||||
|
@ -162,8 +216,11 @@ static BOOL CreateGLScreen(const char *caption, unsigned *xOffsetPtr, unsigned *
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Configuration
|
||||
|
||||
Configuration file management and input settings.
|
||||
******************************************************************************/
|
||||
|
||||
#define CONFIG_FILE_PATH "Config/Supermodel.ini"
|
||||
|
@ -172,19 +229,12 @@ static BOOL CreateGLScreen(const char *caption, unsigned *xOffsetPtr, unsigned *
|
|||
";\n"
|
||||
|
||||
// Create and configure inputs
|
||||
static CInputs *CreateInputs(CInputSystem *InputSystem, BOOL configure)
|
||||
static bool ConfigureInputs(CInputs *Inputs, bool configure)
|
||||
{
|
||||
// Create and initialize inputs
|
||||
CInputs* Inputs = new CInputs(InputSystem);
|
||||
if (!Inputs->Initialize())
|
||||
{
|
||||
ErrorLog("Unable to initalize inputs.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Open and parse configuration file
|
||||
CINIFile INI;
|
||||
INI.Open(CONFIG_FILE_PATH); // doesn't matter if it exists or not, will get overwritten
|
||||
INI.SetDefaultSectionName("Global");
|
||||
INI.Parse();
|
||||
|
||||
Inputs->ReadFromINIFile(&INI, "Global");
|
||||
|
@ -195,10 +245,7 @@ static CInputs *CreateInputs(CInputSystem *InputSystem, BOOL configure)
|
|||
// Open an SDL window
|
||||
unsigned xOffset, yOffset, xRes=496, yRes=384;
|
||||
if (OKAY != CreateGLScreen("Supermodel - Configuring Inputs...",&xOffset,&yOffset,&xRes,&yRes,FALSE,FALSE))
|
||||
{
|
||||
ErrorLog("Unable to start SDL to configure inputs.\n");
|
||||
return NULL;
|
||||
}
|
||||
return (bool) ErrorLog("Unable to start SDL to configure inputs.\n");
|
||||
|
||||
// Configure the inputs
|
||||
if (Inputs->ConfigureInputs(NULL, xOffset, yOffset, xRes, yRes))
|
||||
|
@ -216,9 +263,82 @@ static CInputs *CreateInputs(CInputSystem *InputSystem, BOOL configure)
|
|||
puts("");
|
||||
}
|
||||
|
||||
return Inputs;
|
||||
INI.Close();
|
||||
return OKAY;
|
||||
}
|
||||
|
||||
// Apply configuration settings from configuration file
|
||||
static void ApplySettings(CInputs *Inputs, CINIFile *INI, const char *section)
|
||||
{
|
||||
unsigned x;
|
||||
string String;
|
||||
|
||||
// Model 3
|
||||
if (OKAY == INI->Get(section, "MultiThreaded", x))
|
||||
g_Config.multiThreaded = x ? true : false;
|
||||
if (OKAY == INI->Get(section, "PowerPCFrequency", x))
|
||||
g_Config.SetPowerPCFrequency(x);
|
||||
|
||||
// 3D renderer
|
||||
INI->Get(section, "VertexShader", g_Config.vertexShaderFile);
|
||||
INI->Get(section, "FragmentShader", g_Config.fragmentShaderFile);
|
||||
|
||||
// SCSP and DSB
|
||||
if (OKAY == INI->Get(section, "SoundVolume", x))
|
||||
g_Config.SetSoundVolume(x);
|
||||
if (OKAY == INI->Get(section, "MusicVolume", x))
|
||||
g_Config.SetMusicVolume(x);
|
||||
if (OKAY == INI->Get(section, "EmulateSCSP", x))
|
||||
g_Config.emulateSCSP = x ? true : false;
|
||||
if (OKAY == INI->Get(section, "EmulateDSB", x))
|
||||
g_Config.emulateDSB = x ? true : false;
|
||||
|
||||
// OSD
|
||||
INI->Get(section, "XResolution", g_Config.xRes);
|
||||
INI->Get(section, "YResolution", g_Config.yRes);
|
||||
if (OKAY == INI->Get(section, "FullScreen", x))
|
||||
g_Config.fullScreen = x ? true : false;
|
||||
if (OKAY == INI->Get(section, "Throttle", x))
|
||||
g_Config.throttle = x ? true : false;
|
||||
if (OKAY == INI->Get(section, "ShowFrameRate", x))
|
||||
g_Config.showFPS = x ? true : false;
|
||||
|
||||
// Inputs
|
||||
if (Inputs != NULL)
|
||||
Inputs->ReadFromINIFile(INI, section);
|
||||
}
|
||||
|
||||
// Read settings (from a specific section) from the config file
|
||||
static void ReadConfigFile(CInputs *Inputs, const char *section)
|
||||
{
|
||||
CINIFile INI;
|
||||
|
||||
INI.Open(CONFIG_FILE_PATH);
|
||||
INI.SetDefaultSectionName("Global"); // required to read settings not associated with a specific section
|
||||
INI.Parse();
|
||||
ApplySettings(Inputs, &INI, section);
|
||||
INI.Close();
|
||||
}
|
||||
|
||||
// Debug
|
||||
static void DumpConfig(void)
|
||||
{
|
||||
printf("MultiThreaded = %d\n", g_Config.multiThreaded);
|
||||
printf("PowerPCFrequency = %d\n", g_Config.GetPowerPCFrequency());
|
||||
printf("EmulateSCSP = %d\n", g_Config.emulateSCSP);
|
||||
printf("EmulateDSB = %d\n", g_Config.emulateDSB);
|
||||
printf("VertexShader = %s\n", g_Config.vertexShaderFile.c_str());
|
||||
printf("FragmentShader = %s\n", g_Config.fragmentShaderFile.c_str());
|
||||
printf("XResolution = %d\n", g_Config.xRes);
|
||||
printf("YResolution = %d\n", g_Config.yRes);
|
||||
printf("FullScreen = %d\n", g_Config.fullScreen);
|
||||
printf("Throttle = %d\n", g_Config.throttle);
|
||||
printf("ShowFrameRate = %d\n", g_Config.showFPS);
|
||||
printf("InputSystem = %s\n", g_Config.GetInputSystem());
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Save States and NVRAM
|
||||
|
||||
|
@ -364,14 +484,11 @@ static void LoadNVRAM(CModel3 *Model3)
|
|||
******************************************************************************/
|
||||
|
||||
#ifdef SUPERMODEL_DEBUGGER
|
||||
int Supermodel(const char *zipFile, CModel3 *Model3, CInputs *Inputs, Debugger::CDebugger *Debugger, unsigned ppcFrequency, BOOL multiThreaded,
|
||||
unsigned xResParam, unsigned yResParam, BOOL keepAspectRatio, BOOL fullScreen, BOOL noThrottle, BOOL showFPS,
|
||||
const char *vsFile, const char *fsFile)
|
||||
int Supermodel(const char *zipFile, CModel3 *Model3, CInputs *Inputs, Debugger::CDebugger *Debugger, CINIFile *CmdLine)
|
||||
{
|
||||
CLogger *oldLogger;
|
||||
#else
|
||||
int Supermodel(const char *zipFile, CInputs *Inputs, unsigned ppcFrequency, BOOL multiThreaded, unsigned xResParam, unsigned yResParam,
|
||||
BOOL keepAspectRatio, BOOL fullScreen, BOOL noThrottle, BOOL showFPS, const char *vsFile, const char *fsFile)
|
||||
int Supermodel(const char *zipFile, CInputs *Inputs, CINIFile *CmdLine)
|
||||
{
|
||||
CModel3 *Model3 = new CModel3();
|
||||
#endif // SUPERMODEL_DEBUGGER
|
||||
|
@ -385,23 +502,30 @@ int Supermodel(const char *zipFile, CInputs *Inputs, unsigned ppcFrequency, BOOL
|
|||
BOOL paused = 0;
|
||||
|
||||
// Info log user options
|
||||
InfoLog("PowerPC frequency: %d Hz", ppcFrequency);
|
||||
InfoLog("Resolution: %dx%d (%s)", xResParam, yResParam, fullScreen?"full screen":"windowed");
|
||||
InfoLog("Frame rate limiting: %s", noThrottle?"Disabled":"Enabled");
|
||||
InfoLog("PowerPC frequency: %d Hz", g_Config.GetPowerPCFrequency());
|
||||
InfoLog("Resolution requested: %dx%d (%s)", g_Config.xRes, g_Config.yRes, g_Config.fullScreen?"full screen":"windowed");
|
||||
InfoLog("Frame rate limiting: %s", g_Config.throttle?"Enabled":"Disabled");
|
||||
|
||||
// Initialize and load ROMs
|
||||
Model3->Init(ppcFrequency, multiThreaded);
|
||||
if (OKAY != Model3->Init())
|
||||
return 1;
|
||||
if (OKAY != Model3->LoadROMSet(Model3GameList, zipFile))
|
||||
return 1;
|
||||
|
||||
// Apply game-specific settings and then, lastly, command line settings
|
||||
ReadConfigFile(Inputs, Model3->GetGameInfo()->id);
|
||||
//DumpConfig();
|
||||
ApplySettings(Inputs, CmdLine, "Global");
|
||||
//DumpConfig();
|
||||
|
||||
// Load NVRAM
|
||||
LoadNVRAM(Model3);
|
||||
|
||||
// Start up SDL and open a GL window
|
||||
xRes = xResParam;
|
||||
yRes = yResParam;
|
||||
xRes = g_Config.xRes;
|
||||
yRes = g_Config.yRes;
|
||||
sprintf(titleStr, "Supermodel - %s", Model3->GetGameInfo()->title);
|
||||
if (OKAY != CreateGLScreen(titleStr,&xOffset,&yOffset,&xRes,&yRes,keepAspectRatio,fullScreen))
|
||||
if (OKAY != CreateGLScreen(titleStr,&xOffset,&yOffset,&xRes,&yRes,TRUE,g_Config.fullScreen))
|
||||
return 1;
|
||||
|
||||
// Initialize audio system
|
||||
|
@ -409,7 +533,7 @@ int Supermodel(const char *zipFile, CInputs *Inputs, unsigned ppcFrequency, BOOL
|
|||
return 1;
|
||||
|
||||
// Hide mouse if fullscreen
|
||||
Inputs->GetInputSystem()->SetMouseVisibility(!fullScreen);
|
||||
Inputs->GetInputSystem()->SetMouseVisibility(!g_Config.fullScreen);
|
||||
|
||||
// Attach the inputs to the emulator
|
||||
Model3->AttachInputs(Inputs);
|
||||
|
@ -417,7 +541,7 @@ int Supermodel(const char *zipFile, CInputs *Inputs, unsigned ppcFrequency, BOOL
|
|||
// Initialize the renderer
|
||||
if (OKAY != Render2D->Init(xOffset, yOffset, xRes, yRes))
|
||||
goto QuitError;
|
||||
if (OKAY != Render3D->Init(xOffset, yOffset, xRes, yRes, vsFile, fsFile))
|
||||
if (OKAY != Render3D->Init(xOffset, yOffset, xRes, yRes))
|
||||
goto QuitError;
|
||||
Model3->AttachRenderers(Render2D,Render3D);
|
||||
|
||||
|
@ -521,7 +645,7 @@ int Supermodel(const char *zipFile, CInputs *Inputs, unsigned ppcFrequency, BOOL
|
|||
// Dump input states
|
||||
Inputs->DumpState(Model3->GetGameInfo());
|
||||
}
|
||||
else if (Inputs->uiToggleCursor->Pressed() && fullScreen)
|
||||
else if (Inputs->uiToggleCursor->Pressed() && g_Config.fullScreen)
|
||||
{
|
||||
// Toggle cursor in full screen mode
|
||||
showCursor = !showCursor;
|
||||
|
@ -536,8 +660,8 @@ int Supermodel(const char *zipFile, CInputs *Inputs, unsigned ppcFrequency, BOOL
|
|||
else if (Inputs->uiToggleFrLimit->Pressed())
|
||||
{
|
||||
// Toggle frame limiting
|
||||
noThrottle = !noThrottle;
|
||||
printf("Frame limiting: %s\n", noThrottle?"Off":"On");
|
||||
g_Config.throttle = !g_Config.throttle;
|
||||
printf("Frame limiting: %s\n", g_Config.throttle?"On":"Off");
|
||||
}
|
||||
#ifdef SUPERMODEL_DEBUGGER
|
||||
else if (Inputs->uiEnterDebugger->Pressed())
|
||||
|
@ -554,7 +678,7 @@ int Supermodel(const char *zipFile, CInputs *Inputs, unsigned ppcFrequency, BOOL
|
|||
currentTicks = currentFPSTicks;
|
||||
|
||||
// FPS
|
||||
if (showFPS)
|
||||
if (g_Config.showFPS)
|
||||
{
|
||||
++fpsFramesElapsed;
|
||||
if((currentFPSTicks-prevFPSTicks) >= 1000) // update FPS every 1 second (each tick is 1 ms)
|
||||
|
@ -567,7 +691,7 @@ int Supermodel(const char *zipFile, CInputs *Inputs, unsigned ppcFrequency, BOOL
|
|||
}
|
||||
|
||||
// Frame limiting/paused
|
||||
if (paused || !noThrottle)
|
||||
if (paused || g_Config.throttle)
|
||||
{
|
||||
++framesElapsed;
|
||||
targetTicks = startTicks + (unsigned) ((float)framesElapsed * 1000.0f/60.0f);
|
||||
|
@ -643,204 +767,6 @@ QuitError:
|
|||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Error and Debug Logging
|
||||
******************************************************************************/
|
||||
|
||||
static CLogger *s_logger = NULL;
|
||||
|
||||
/*
|
||||
* Returns the current logger.
|
||||
*/
|
||||
CLogger *GetLogger()
|
||||
{
|
||||
return s_logger;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the current logger.
|
||||
*/
|
||||
void SetLogger(CLogger *logger)
|
||||
{
|
||||
s_logger = logger;
|
||||
}
|
||||
|
||||
/*
|
||||
* DebugLog(fmt, ...):
|
||||
*
|
||||
* Logs a debug message with the logger.
|
||||
*
|
||||
* Parameters:
|
||||
* fmt Format string (same as printf()).
|
||||
* ... Variable number of arguments as required by format string.
|
||||
*/
|
||||
void DebugLog(const char *fmt, ...)
|
||||
{
|
||||
if (s_logger == NULL)
|
||||
return;
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
s_logger->DebugLog(fmt, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
/*
|
||||
* InfoLog(fmt, ...);
|
||||
*
|
||||
* Logs an info message with the logger.
|
||||
*
|
||||
* Parameters:
|
||||
* fmt Format string (same as printf()).
|
||||
* ... Variable number of arguments as required by format string.
|
||||
*/
|
||||
void InfoLog(const char *fmt, ...)
|
||||
{
|
||||
if (s_logger == NULL)
|
||||
return;
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
s_logger->InfoLog(fmt, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
/*
|
||||
* ErrorLog(fmt, ...):
|
||||
*
|
||||
* Logs an error message with the logger.
|
||||
*
|
||||
* Parameters:
|
||||
* fmt Format string (same as printf()).
|
||||
* ... Variable number of arguments as required by format string.
|
||||
*
|
||||
* Returns:
|
||||
* Always returns FAIL.
|
||||
*/
|
||||
BOOL ErrorLog(const char *fmt, ...)
|
||||
{
|
||||
if (s_logger == NULL)
|
||||
return FAIL;
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
s_logger->ErrorLog(fmt, vl);
|
||||
va_end(vl);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
#define DEBUG_LOG_FILE "debug.log"
|
||||
#define ERROR_LOG_FILE "error.log"
|
||||
|
||||
/*
|
||||
* Default logger that logs to debug and error log files.
|
||||
*/
|
||||
class CFileLogger : public CLogger
|
||||
{
|
||||
private:
|
||||
const char *m_debugLogFile;
|
||||
const char *m_errorLogFile;
|
||||
|
||||
public:
|
||||
CFileLogger(const char *debugLogFile, const char *errorLogFile) :
|
||||
m_debugLogFile(debugLogFile), m_errorLogFile(errorLogFile)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/*
|
||||
* DebugLog(fmt, ...):
|
||||
*
|
||||
* Prints to debug log. The file is opened and closed each time so that its
|
||||
* contents are preserved even if the program crashes.
|
||||
*/
|
||||
void DebugLog(const char *fmt, va_list vl)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
char string[1024];
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(m_debugLogFile, "ab");
|
||||
if (NULL != fp)
|
||||
{
|
||||
vsprintf(string, fmt, vl);
|
||||
fprintf(fp, string);
|
||||
fclose(fp);
|
||||
}
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
/*
|
||||
* InfoLog(fmt, ...);
|
||||
*
|
||||
* Prints information to the error log file but does not print to stderr. This
|
||||
* is useful for logging non-error information.
|
||||
*/
|
||||
void InfoLog(const char *fmt, va_list vl)
|
||||
{
|
||||
char string[4096];
|
||||
FILE *fp;
|
||||
|
||||
vsprintf(string, fmt, vl);
|
||||
|
||||
fp = fopen(m_errorLogFile, "ab");
|
||||
if (NULL != fp)
|
||||
{
|
||||
fprintf(fp, "%s\n", string);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
CLogger::DebugLog("Info: ");
|
||||
CLogger::DebugLog(string);
|
||||
CLogger::DebugLog("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* ErrorLog(fmt, ...):
|
||||
*
|
||||
* Prints an error to stderr and the error log file.
|
||||
*/
|
||||
void ErrorLog(const char *fmt, va_list vl)
|
||||
{
|
||||
char string[4096];
|
||||
FILE *fp;
|
||||
|
||||
vsprintf(string, fmt, vl);
|
||||
fprintf(stderr, "Error: %s\n", string);
|
||||
|
||||
fp = fopen(m_errorLogFile, "ab");
|
||||
if (NULL != fp)
|
||||
{
|
||||
fprintf(fp, "%s\n", string);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
CLogger::DebugLog("Error: ");
|
||||
CLogger::DebugLog(string);
|
||||
CLogger::DebugLog("\n");
|
||||
}
|
||||
|
||||
void ClearLogs()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
ClearLog(DEBUG_LOG_FILE, "Supermodel v"SUPERMODEL_VERSION" Debug Log");
|
||||
#endif // DEBUG
|
||||
ClearLog(ERROR_LOG_FILE, "Supermodel v"SUPERMODEL_VERSION" Error Log");
|
||||
}
|
||||
|
||||
// Clear log file
|
||||
void ClearLog(const char *file, const char *title)
|
||||
{
|
||||
FILE *fp = fopen(file, "w");
|
||||
if (NULL != fp)
|
||||
{
|
||||
unsigned i;
|
||||
fprintf(fp, "%s\n", title);
|
||||
for (i = 0; i < strlen(title); i++)
|
||||
fputc('-', fp);
|
||||
fprintf(fp, "\n\n");
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
Diagnostic Commands
|
||||
******************************************************************************/
|
||||
|
@ -988,10 +914,12 @@ static void Help(void)
|
|||
puts("");
|
||||
puts("General Options:");
|
||||
puts(" -?, -h Print this help text");
|
||||
puts(" -print-games List supported games");
|
||||
puts(" -print-games List supported games and quit");
|
||||
puts("");
|
||||
puts("Emulation Options:");
|
||||
puts(" -ppc-frequency=<f> Set PowerPC frequency in MHz [Default: 25]");
|
||||
puts(" -ppc-frequency=<f> Set PowerPC frequency in MHz [Default: 40]");
|
||||
puts(" -no-scsp Disable Sega Custom Sound Processor (sound effects)");
|
||||
puts(" -no-dsb Disable Digital Sound Board (MPEG music)");
|
||||
puts(" -multi-threaded Enable multi-threading");
|
||||
#ifdef SUPERMODEL_DEBUGGER
|
||||
puts(" -disable-debugger Completely disable debugger functionality");
|
||||
|
@ -1007,6 +935,10 @@ static void Help(void)
|
|||
puts(" -vert-shader=<file> Load 3D vertex shader from external file");
|
||||
puts(" -frag-shader=<file> Load 3D fragment shader from external file");
|
||||
#endif
|
||||
puts("");
|
||||
puts("Audio Options:");
|
||||
puts(" -sound-volume=<v> Set volume of sound effects in % [Default: 100]");
|
||||
puts(" -music-volume=<v> Set volume of MPEG music in % [Default: 100]");
|
||||
puts("");
|
||||
puts("Input Options:");
|
||||
puts(" -input-system=<s> Set input system [Default: SDL]");
|
||||
|
@ -1017,7 +949,7 @@ static void Help(void)
|
|||
#ifdef DEBUG
|
||||
puts(" -dis=<addr>[,n] Disassemble PowerPC code from CROM");
|
||||
#endif
|
||||
puts(" -print-gl-info Print extensive OpenGL information\n");
|
||||
puts(" -print-gl-info Print extensive OpenGL information and quit\n");
|
||||
}
|
||||
|
||||
// Print game list
|
||||
|
@ -1045,13 +977,14 @@ static void PrintGameList(void)
|
|||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CINIFile CmdLine; // not associated with any files, holds command line options
|
||||
int i, ret;
|
||||
int cmd=0, fileIdx=0, cmdMultiThreaded=0, cmdFullScreen=0, cmdNoThrottle=0, cmdShowFPS=0, cmdPrintInputs=0, cmdConfigInputs=0, cmdPrintGames=0, cmdDis=0, cmdPrintGLInfo=0;
|
||||
int fileIdx=0;
|
||||
bool cmdPrintInputs=false, cmdConfigInputs=false, cmdDis=false;
|
||||
#ifdef SUPERMODEL_DEBUGGER
|
||||
int cmdDisableDebugger = 0, cmdEnterDebugger=0;
|
||||
int cmdEnterDebugger=false;
|
||||
#endif // SUPERMODEL_DEBUGGER
|
||||
unsigned n, xRes=496, yRes=384, ppcFrequency=25000000;
|
||||
char *vsFile = NULL, *fsFile = NULL, *inpSysName = NULL;
|
||||
unsigned n;
|
||||
UINT32 addr;
|
||||
|
||||
Title();
|
||||
|
@ -1065,8 +998,21 @@ int main(int argc, char **argv)
|
|||
CFileLogger Logger(DEBUG_LOG_FILE, ERROR_LOG_FILE);
|
||||
Logger.ClearLogs();
|
||||
SetLogger(&Logger);
|
||||
|
||||
// Read global settings from INI file
|
||||
ReadConfigFile(NULL, "Global");
|
||||
//DumpConfig();
|
||||
|
||||
// Parse command line
|
||||
/*
|
||||
* Parse command line.
|
||||
*
|
||||
* Settings are stored in CmdLine so that they can be applied later, after
|
||||
* game-specific settings are read from the configuration file (which
|
||||
* requires the ROM set to be identified and therefore is done later).
|
||||
*
|
||||
* Some commands are processed here directly.
|
||||
*/
|
||||
CmdLine.SetDefaultSectionName("Global"); // command line settings are global-level
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (!strcmp(argv[i],"-h") || !strcmp(argv[i],"-?"))
|
||||
|
@ -1075,7 +1021,10 @@ int main(int argc, char **argv)
|
|||
return 0;
|
||||
}
|
||||
else if (!strcmp(argv[i],"-print-games"))
|
||||
cmd = cmdPrintGames = 1;
|
||||
{
|
||||
PrintGameList();
|
||||
return 0;
|
||||
}
|
||||
else if (!strncmp(argv[i],"-ppc-frequency",14))
|
||||
{
|
||||
int f;
|
||||
|
@ -1083,21 +1032,45 @@ int main(int argc, char **argv)
|
|||
if (ret != 1)
|
||||
ErrorLog("-ppc-frequency requires a frequency.");
|
||||
else
|
||||
{
|
||||
if ((f<1) || (f>1000)) // limit to 1-1000MHz
|
||||
ErrorLog("PowerPC frequency must be between 1 and 1000 MHz. Ignoring.");
|
||||
else
|
||||
ppcFrequency = f*1000000;
|
||||
}
|
||||
CmdLine.Set("Global", "PowerPCFrequency", f);
|
||||
}
|
||||
else if (!strcmp(argv[i],"-multi-threaded"))
|
||||
{
|
||||
n = 1;
|
||||
CmdLine.Set("Global", "MultiThreaded", n);
|
||||
}
|
||||
else if (!strncmp(argv[i],"-multi-threaded", 16))
|
||||
cmd = cmdMultiThreaded = 1;
|
||||
#ifdef SUPERMODEL_DEBUGGER
|
||||
else if (!strncmp(argv[i],"-disable-debugger",17))
|
||||
cmd = cmdDisableDebugger = 1;
|
||||
else if (!strncmp(argv[i],"-enter-debugger",15))
|
||||
cmd = cmdEnterDebugger = 1;
|
||||
else if (!strncmp(argv[i],"-disable-debugger"))
|
||||
g_Config.disableDebugger = true;
|
||||
else if (!strcmp(argv[i],"-enter-debugger"))
|
||||
cmdEnterDebugger = true;
|
||||
#endif // SUPERMODEL_DEBUGGER
|
||||
else if (!strncmp(argv[i],"-sound-vol",10))
|
||||
{
|
||||
ret = sscanf(&argv[i][10],"=%d",&n);
|
||||
if (ret != 1)
|
||||
ErrorLog("-sound-vol requires a volume setting.");
|
||||
else
|
||||
CmdLine.Set("Global", "SoundVolume", n);
|
||||
}
|
||||
else if (!strncmp(argv[i],"-music-vol",10))
|
||||
{
|
||||
ret = sscanf(&argv[i][10],"=%d",&n);
|
||||
if (ret != 1)
|
||||
ErrorLog("-music-vol requires a volume setting.");
|
||||
else
|
||||
CmdLine.Set("Global", "MusicVolume", n);
|
||||
}
|
||||
else if (!strcmp(argv[i], "-no-scsp"))
|
||||
{
|
||||
n = 0;
|
||||
CmdLine.Set("Global", "EmulateSCSP", n);
|
||||
}
|
||||
else if (!strcmp(argv[i], "-no-dsb"))
|
||||
{
|
||||
n = 0;
|
||||
CmdLine.Set("Global", "EmulateDSB", n);
|
||||
}
|
||||
else if (!strncmp(argv[i],"-res",4))
|
||||
{
|
||||
unsigned x, y;
|
||||
|
@ -1107,56 +1080,68 @@ int main(int argc, char **argv)
|
|||
ErrorLog("-res requires both a width and a height.");
|
||||
else
|
||||
{
|
||||
xRes = x;
|
||||
yRes = y;
|
||||
CmdLine.Set("Global", "XResolution", x);
|
||||
CmdLine.Set("Global", "YResolution", y);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[i],"-fullscreen"))
|
||||
cmd = cmdFullScreen = 1;
|
||||
{
|
||||
n = 1;
|
||||
CmdLine.Set("Global", "FullScreen", n);
|
||||
}
|
||||
else if (!strcmp(argv[i],"-no-throttle"))
|
||||
cmd = cmdNoThrottle = 1;
|
||||
{
|
||||
n = 0;
|
||||
CmdLine.Set("Global", "Throttle", n);
|
||||
}
|
||||
else if (!strcmp(argv[i],"-show-fps"))
|
||||
cmd = cmdShowFPS = 1;
|
||||
{
|
||||
n = 1;
|
||||
CmdLine.Set("Global", "ShowFrameRate", n);
|
||||
}
|
||||
else if (!strncmp(argv[i],"-vert-shader=",13))
|
||||
{
|
||||
if (argv[i][13] == '\0')
|
||||
ErrorLog("-vert-shader requires a file path.");
|
||||
else
|
||||
vsFile = &argv[i][13];
|
||||
CmdLine.Set("Global", "VertexShader", &argv[i][13]);
|
||||
}
|
||||
else if (!strncmp(argv[i],"-frag-shader=",13))
|
||||
{
|
||||
if (argv[i][13] == '\0')
|
||||
ErrorLog("-frag-shader requires a file path.");
|
||||
else
|
||||
fsFile = &argv[i][13];
|
||||
CmdLine.Set("Global", "FragmentShader", &argv[i][13]);
|
||||
}
|
||||
else if (!strncmp(argv[i],"-input-system=", 14))
|
||||
{
|
||||
if (argv[i][14] == '\0')
|
||||
ErrorLog("-input-system requires an input system name.");
|
||||
else
|
||||
inpSysName = &argv[i][14];
|
||||
CmdLine.Set("Global", "InputSystem", &argv[i][14]);
|
||||
}
|
||||
else if (!strcmp(argv[i],"-print-inputs"))
|
||||
cmd = cmdPrintInputs = 1;
|
||||
cmdPrintInputs = true;
|
||||
else if (!strcmp(argv[i],"-config-inputs"))
|
||||
cmd = cmdConfigInputs = 1;
|
||||
cmdConfigInputs = true;
|
||||
else if (!strncmp(argv[i],"-dis",4))
|
||||
{
|
||||
ret = sscanf(&argv[i][4],"=%X,%X",&addr,&n);
|
||||
if (ret == 1)
|
||||
{
|
||||
n = 16;
|
||||
cmd = cmdDis = 1;
|
||||
cmdDis = true;
|
||||
}
|
||||
else if (ret == 2)
|
||||
cmd = cmdDis = 1;
|
||||
cmdDis = true;
|
||||
else
|
||||
ErrorLog("-dis requires address and, optionally, number of instructions.");
|
||||
}
|
||||
else if (!strcmp(argv[i],"-print-gl-info"))
|
||||
cmd = cmdPrintGLInfo = 1;
|
||||
{
|
||||
PrintGLInfo(FALSE);
|
||||
return 0;
|
||||
}
|
||||
else if (argv[i][0] == '-')
|
||||
ErrorLog("Ignoring invalid option: %s.", argv[i]);
|
||||
else
|
||||
|
@ -1175,6 +1160,7 @@ int main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Create input system (default is SDL) and debugger
|
||||
CInputSystem *InputSystem = NULL;
|
||||
CInputs *Inputs = NULL;
|
||||
int exitCode = 0;
|
||||
|
@ -1183,27 +1169,33 @@ int main(int argc, char **argv)
|
|||
Debugger::CSupermodelDebugger *Debugger = NULL;
|
||||
#endif // SUPERMODEL_DEBUGGER
|
||||
|
||||
// Create input system (default is SDL)
|
||||
if (inpSysName == NULL || stricmp(inpSysName, "sdl") == 0)
|
||||
if (stricmp(g_Config.GetInputSystem(), "sdl") == 0)
|
||||
InputSystem = new CSDLInputSystem();
|
||||
#ifdef SUPERMODEL_WIN32
|
||||
else if (stricmp(inpSysName, "dinput") == 0)
|
||||
else if (stricmp(g_Config.GetInputSystem(), "dinput") == 0)
|
||||
InputSystem = new CDirectInputSystem(false, false, false);
|
||||
else if (stricmp(inpSysName, "xinput") == 0)
|
||||
else if (stricmp(g_Config.GetInputSystem(), "xinput") == 0)
|
||||
InputSystem = new CDirectInputSystem(false, true, false);
|
||||
else if (stricmp(inpSysName, "rawinput") == 0)
|
||||
else if (stricmp(g_Config.GetInputSystem(), "rawinput") == 0)
|
||||
InputSystem = new CDirectInputSystem(true, false, false);
|
||||
#endif // SUPERMODEL_WIN32
|
||||
else
|
||||
{
|
||||
ErrorLog("Unknown input system: '%s'.\n", inpSysName);
|
||||
ErrorLog("Unknown input system: '%s'.\n", g_Config.GetInputSystem());
|
||||
exitCode = 1;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// Create inputs from input system (configuring them if required)
|
||||
Inputs = CreateInputs(InputSystem, cmdConfigInputs);
|
||||
if (Inputs == NULL)
|
||||
Inputs = new CInputs(InputSystem);
|
||||
if (!Inputs->Initialize())
|
||||
{
|
||||
ErrorLog("Unable to initalize inputs.\n");
|
||||
exitCode = 1;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (ConfigureInputs(Inputs, cmdConfigInputs))
|
||||
{
|
||||
exitCode = 1;
|
||||
goto Exit;
|
||||
|
@ -1215,22 +1207,7 @@ int main(int argc, char **argv)
|
|||
InputSystem->PrintSettings();
|
||||
}
|
||||
|
||||
// Process commands that don't require ROM set
|
||||
if (cmd)
|
||||
{
|
||||
if (cmdPrintGames)
|
||||
{
|
||||
PrintGameList();
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (cmdPrintGLInfo)
|
||||
{
|
||||
PrintGLInfo(FALSE);
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
// From this point onwards, a ROM set is needed
|
||||
if (fileIdx == 0)
|
||||
{
|
||||
ErrorLog("No ROM set specified.");
|
||||
|
@ -1238,22 +1215,18 @@ int main(int argc, char **argv)
|
|||
goto Exit;
|
||||
}
|
||||
|
||||
// Process commands that require ROMs
|
||||
if (cmd)
|
||||
{
|
||||
if (cmdDis)
|
||||
{
|
||||
if (OKAY != DisassembleCROM(argv[fileIdx], addr, n))
|
||||
exitCode = 1;
|
||||
goto Exit;
|
||||
}
|
||||
if (cmdDis)
|
||||
{
|
||||
if (OKAY != DisassembleCROM(argv[fileIdx], addr, n))
|
||||
exitCode = 1;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
#ifdef SUPERMODEL_DEBUGGER
|
||||
// Create Model3
|
||||
Model3 = new CModel3();
|
||||
// Create Supermodel debugger unless debugging is disabled
|
||||
if (!cmdDisableDebugger)
|
||||
if (!g_Config.disableDebugger)
|
||||
{
|
||||
Debugger = new Debugger::CSupermodelDebugger(Model3, Inputs, &Logger);
|
||||
// If -enter-debugger option was set force debugger to break straightaway
|
||||
|
@ -1261,13 +1234,13 @@ int main(int argc, char **argv)
|
|||
Debugger->ForceBreak(true);
|
||||
}
|
||||
// Fire up Supermodel with debugger
|
||||
exitCode = Supermodel(argv[fileIdx],Model3,Inputs,Debugger,ppcFrequency,cmdMultiThreaded,xRes,yRes,TRUE,cmdFullScreen,cmdNoThrottle,cmdShowFPS,vsFile,fsFile);
|
||||
exitCode = Supermodel(argv[fileIdx],Model3,Inputs,Debugger,&CmdLine);
|
||||
if (Debugger != NULL)
|
||||
delete Debugger;
|
||||
delete Model3;
|
||||
#else
|
||||
// Fire up Supermodel
|
||||
exitCode = Supermodel(argv[fileIdx],Inputs,ppcFrequency,cmdMultiThreaded,xRes,yRes,TRUE,cmdFullScreen,cmdNoThrottle,cmdShowFPS,vsFile,fsFile);
|
||||
exitCode = Supermodel(argv[fileIdx],Inputs,&CmdLine);
|
||||
#endif // SUPERMODEL_DEBUGGER
|
||||
|
||||
Exit:
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
* Fundamental data types. This file is used by both C++ and C modules, so it
|
||||
* must NOT include any C++-specific constructs. Some modules may elect to
|
||||
* include it directly rather than through Supermodel.h.
|
||||
*
|
||||
* All ports must define this file.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_TYPES_H
|
||||
|
|
|
@ -119,7 +119,7 @@ int g,snd_eof=0;
|
|||
|
||||
if (header.protection_bit==0) getcrc();
|
||||
|
||||
printf("%d Hz, layer %d\n", t_sampling_frequency[header.ID][header.sampling_frequency], header.layer);
|
||||
//printf("%d Hz, layer %d\n", t_sampling_frequency[header.ID][header.sampling_frequency], header.layer);
|
||||
|
||||
if (setup_audio(&header)!=0) {
|
||||
warn("Cannot set up audio. Exiting\n");
|
||||
|
|
|
@ -523,7 +523,7 @@ static int min_cycles = 99999999;
|
|||
|
||||
if (cnt2-cnt1 < min_cycles) {
|
||||
min_cycles = cnt2-cnt1;
|
||||
printf("%d cycles\n", min_cycles);
|
||||
//printf("%d cycles\n", min_cycles);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -546,7 +546,7 @@ static int min_cycles = 99999999;
|
|||
|
||||
if (cnt2-cnt1 < min_cycles) {
|
||||
min_cycles = cnt2-cnt1;
|
||||
printf("%d cycles, sfb %d\n", min_cycles, sfb);
|
||||
//printf("%d cycles, sfb %d\n", min_cycles, sfb);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1503,7 +1503,7 @@ static int min_cycles = 99999999;
|
|||
|
||||
if (cnt2-cnt1 < min_cycles) {
|
||||
min_cycles = cnt2-cnt1;
|
||||
printf("%d, %d cycles, %d\n", cnt3-cnt1, min_cycles, start);
|
||||
//printf("%d, %d cycles, %d\n", cnt3-cnt1, min_cycles, start);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -28,6 +28,12 @@
|
|||
#ifndef INCLUDED_SUPERMODEL_H
|
||||
#define INCLUDED_SUPERMODEL_H
|
||||
|
||||
// Used throughout Supermodel
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Program-Wide Definitions
|
||||
******************************************************************************/
|
||||
|
@ -38,8 +44,11 @@
|
|||
/******************************************************************************
|
||||
OS-Dependent (OSD) Items
|
||||
|
||||
Everything here must be provided by the OSD layer. Include files should be
|
||||
located in the OSD directories for each port.
|
||||
Everything here must be provided by the OSD layer. The following include files
|
||||
must be located in the OSD directories for each port:
|
||||
|
||||
Types.h Defines fundamental data types.
|
||||
OSDConfig.h COSDConfig class (OSD-specific configuration settings).
|
||||
******************************************************************************/
|
||||
|
||||
// stricmp() is non-standard, apparently...
|
||||
|
@ -49,6 +58,7 @@
|
|||
#define stricmp strcasecmp
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Fundamental Data Types:
|
||||
*
|
||||
|
@ -68,58 +78,21 @@
|
|||
* specific stuff. Some modules may choose to include it directly rather than
|
||||
* use Supermodel.h, so it must exist.
|
||||
*/
|
||||
#include "Types.h"
|
||||
|
||||
// OSD Interfaces
|
||||
#include "Thread.h"
|
||||
#include "Audio.h"
|
||||
#include "Types.h" // located in OSD/<port>/ directory
|
||||
|
||||
/*
|
||||
* Error and Debug Logging
|
||||
* OSD Header Files
|
||||
*/
|
||||
|
||||
/*
|
||||
* DebugLog(fmt, ...):
|
||||
*
|
||||
* Prints debugging information. The OSD layer may choose to print this to a
|
||||
* log file, the screen, neither, or both. Newlines and other formatting codes
|
||||
* must be explicitly included.
|
||||
*
|
||||
* Parameters:
|
||||
* fmt A format string (the same as printf()).
|
||||
* ... Variable number of arguments, as required by format string.
|
||||
*/
|
||||
extern void DebugLog(const char *fmt, ...);
|
||||
// Error logging interface
|
||||
#include "OSD/Logger.h"
|
||||
|
||||
/*
|
||||
* ErrorLog(fmt, ...):
|
||||
*
|
||||
* Prints error information. Errors need not require program termination and
|
||||
* may simply be informative warnings to the user. Newlines should not be
|
||||
* included in the format string -- they are automatically added at the end of
|
||||
* a line.
|
||||
*
|
||||
* Parameters:
|
||||
* fmt A format string (the same as printf()).
|
||||
* ... Variable number of arguments, as required by format string.
|
||||
*
|
||||
* Returns:
|
||||
* Must always return FAIL.
|
||||
*/
|
||||
extern BOOL ErrorLog(const char *fmt, ...);
|
||||
// OSD configuration
|
||||
#include "OSDConfig.h" // located in OSD/<port>/ directory
|
||||
|
||||
/*
|
||||
* InfoLog(fmt, ...);
|
||||
*
|
||||
* Prints information to the error log file but does not print to stderr. This
|
||||
* is useful for logging non-error information. Newlines are automatically
|
||||
* appended.
|
||||
*
|
||||
* Parameters:
|
||||
* fmt Format string (same as printf()).
|
||||
* ... Variable number of arguments as required by format string.
|
||||
*/
|
||||
extern void InfoLog(const char *fmt, ...);
|
||||
// OSD Interfaces
|
||||
#include "OSD/Thread.h"
|
||||
#include "OSD/Audio.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -128,10 +101,7 @@ extern void InfoLog(const char *fmt, ...);
|
|||
All primary header files for modules used throughout Supermodel are included
|
||||
here, except for external packages and APIs.
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Games.h"
|
||||
#include "ROMLoad.h"
|
||||
#include "INIFile.h"
|
||||
|
@ -168,6 +138,7 @@ extern void InfoLog(const char *fmt, ...);
|
|||
#include "Model3/SoundBoard.h"
|
||||
#include "Model3/DSB.h"
|
||||
#include "Model3/Model3.h"
|
||||
#include "Config.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
|
|
Loading…
Reference in a new issue