Massive internal change: removed CConfig object and replaced it with a hierarchical config object system (Util::Config::Node). Games are now defined in an XML file. Hopefully I didn't break too many things :/

This commit is contained in:
Bart Trzynadlowski 2017-03-27 03:19:15 +00:00
parent 26a4417a5f
commit f34e25dfc7
48 changed files with 5106 additions and 5382 deletions

View file

@ -38,7 +38,7 @@ BITS = 64
# #
# Include console-based debugger in emulator ('yes' or 'no') # Include console-based debugger in emulator ('yes' or 'no')
# #
ENABLE_DEBUGGER = no ENABLE_DEBUGGER = yes
############################################################################### ###############################################################################
@ -58,7 +58,7 @@ BOOST_INCLUDEPATH = /mingw64/boost_1_55_0
ifeq ($(strip $(BITS)),64) ifeq ($(strip $(BITS)),64)
SDL_LIBPATH = /mingw64/lib64 SDL_LIBPATH = /mingw64/lib64
#SDL_INCLUDEPATH = /mingw64/x86_64-w64-mingw32/include/SDL #SDL_INCLUDEPATH = /mingw64/x86_64-w64-mingw32/include/SDL
SDL_INCLUDEPATH = /mingw64/SDL-1.2.15/include SDL_INCLUDEPATH = c:\tdm-gcc-64\include\SDL
else else
SDL_LIBPATH = /mingw/lib SDL_LIBPATH = /mingw/lib
SDL_INCLUDEPATH = /mingw/include/SDL SDL_INCLUDEPATH = /mingw/include/SDL
@ -100,7 +100,7 @@ LD = g++
COMPILER_FLAGS = -I$(SDL_INCLUDEPATH) -ISrc/ -ISrc/OSD/ -ISrc/OSD/SDL/ -ISrc/OSD/Windows/ -c -Wall -DSUPERMODEL_WIN32 -DGLEW_STATIC -O3 COMPILER_FLAGS = -I$(SDL_INCLUDEPATH) -ISrc/ -ISrc/OSD/ -ISrc/OSD/SDL/ -ISrc/OSD/Windows/ -c -Wall -DSUPERMODEL_WIN32 -DGLEW_STATIC -O3
CFLAGS = $(COMPILER_FLAGS) CFLAGS = $(COMPILER_FLAGS)
CPPFLAGS = $(COMPILER_FLAGS) -I$(BOOST_INCLUDEPATH) -std=c++11 CPPFLAGS = $(COMPILER_FLAGS) -I$(BOOST_INCLUDEPATH) -std=c++11
LFLAGS = -o $(OUTFILE) $(OBJ) -L$(SDL_LIBPATH) -lmingw32 -lSDLmain -lSDL -lopengl32 -lglu32 -ldinput8 -ldxguid -lole32 -loleaut32 -lwbemuuid -lz -s #-l:$(WINSDK_LIBPATH)/WbemUuid.lib -s LFLAGS = -o $(OUTFILE) $(OBJ) -L$(SDL_LIBPATH) -lmingw32 -lSDLmain -lSDL -lopengl32 -lglu32 -ldinput8 -ldxguid -lole32 -loleaut32 -lwbemuuid -lz -s # -l:$(WINSDK_LIBPATH)/WbemUuid.lib -s
# #
# Build options... # Build options...
@ -119,11 +119,11 @@ endif
# #
# Objects and Dependencies # Objects and Dependencies
# #
OBJ = $(OBJ_DIR)/Format.o $(OBJ_DIR)/NewConfig.o \ OBJ = $(OBJ_DIR)/PPCDisasm.o $(OBJ_DIR)/Games.o $(OBJ_DIR)/INIFile.o $(OBJ_DIR)/BlockFile.o $(OBJ_DIR)/93C46.o \
$(OBJ_DIR)/PPCDisasm.o $(OBJ_DIR)/Games.o $(OBJ_DIR)/Config.o $(OBJ_DIR)/INIFile.o $(OBJ_DIR)/BlockFile.o $(OBJ_DIR)/93C46.o \
$(OBJ_DIR)/ROMLoad.o $(OBJ_DIR)/unzip.o $(OBJ_DIR)/ioapi.o $(OBJ_DIR)/Error.o $(OBJ_DIR)/glew.o $(OBJ_DIR)/Shader.o \ $(OBJ_DIR)/ROMLoad.o $(OBJ_DIR)/unzip.o $(OBJ_DIR)/ioapi.o $(OBJ_DIR)/Error.o $(OBJ_DIR)/glew.o $(OBJ_DIR)/Shader.o \
$(OBJ_DIR)/Real3D.o $(OBJ_DIR)/Legacy3D.o $(OBJ_DIR)/Models.o $(OBJ_DIR)/TextureRefs.o \ $(OBJ_DIR)/Real3D.o $(OBJ_DIR)/Legacy3D.o $(OBJ_DIR)/Models.o $(OBJ_DIR)/TextureRefs.o \
$(OBJ_DIR)/New3D.o $(OBJ_DIR)/Mat4.o $(OBJ_DIR)/Model.o $(OBJ_DIR)/PolyHeader.o $(OBJ_DIR)/Texture.o $(OBJ_DIR)/TextureSheet.o $(OBJ_DIR)/VBO.o $(OBJ_DIR)/Vec.o $(OBJ_DIR)/R3DShader.o $(OBJ_DIR)/R3DFloat.o \ $(OBJ_DIR)/New3D.o $(OBJ_DIR)/Mat4.o $(OBJ_DIR)/Model.o $(OBJ_DIR)/PolyHeader.o $(OBJ_DIR)/Texture.o $(OBJ_DIR)/TextureSheet.o $(OBJ_DIR)/VBO.o $(OBJ_DIR)/Vec.o $(OBJ_DIR)/R3DShader.o $(OBJ_DIR)/R3DFloat.o \
$(OBJ_DIR)/R3DScrollFog.o \
$(OBJ_DIR)/Render2D.o $(OBJ_DIR)/TileGen.o \ $(OBJ_DIR)/Render2D.o $(OBJ_DIR)/TileGen.o \
$(OBJ_DIR)/Model3.o $(OBJ_DIR)/ppc.o $(OBJ_DIR)/Main.o $(OBJ_DIR)/Audio.o $(OBJ_DIR)/Thread.o $(OBJ_DIR)/SoundBoard.o \ $(OBJ_DIR)/Model3.o $(OBJ_DIR)/ppc.o $(OBJ_DIR)/Main.o $(OBJ_DIR)/Audio.o $(OBJ_DIR)/Thread.o $(OBJ_DIR)/SoundBoard.o \
$(OBJ_DIR)/SCSP.o $(OBJ_DIR)/SCSPDSP.o $(OBJ_DIR)/68K.o $(OBJ_DIR)/m68kcpu.o $(OBJ_DIR)/m68kopnz.o $(OBJ_DIR)/m68kopdm.o \ $(OBJ_DIR)/SCSP.o $(OBJ_DIR)/SCSPDSP.o $(OBJ_DIR)/68K.o $(OBJ_DIR)/m68kcpu.o $(OBJ_DIR)/m68kopnz.o $(OBJ_DIR)/m68kopdm.o \
@ -137,7 +137,8 @@ OBJ = $(OBJ_DIR)/Format.o $(OBJ_DIR)/NewConfig.o \
$(OBJ_DIR)/amp_util.o \ $(OBJ_DIR)/amp_util.o \
$(OBJ_DIR)/Crypto.o \ $(OBJ_DIR)/Crypto.o \
$(OBJ_DIR)/Logger.o \ $(OBJ_DIR)/Logger.o \
$(OBJ_DIR)/tinyxml2.o $(OBJ_DIR)/tinyxml2.o \
$(OBJ_DIR)/ByteSwap.o $(OBJ_DIR)/Format.o $(OBJ_DIR)/NewConfig.o $(OBJ_DIR)/ConfigBuilders.o $(OBJ_DIR)/GameLoader.o
# If built-in debugger enabled, include all debugging classes # If built-in debugger enabled, include all debugging classes
@ -159,9 +160,9 @@ ppcd: $(BIN_DIR) $(OBJ_DIR)
$(CXX) Src/CPU/PowerPC/PPCDisasm.cpp $(CPPFLAGS) -DSTANDALONE -o $(OBJ_DIR)/ppcd.o $(CXX) Src/CPU/PowerPC/PPCDisasm.cpp $(CPPFLAGS) -DSTANDALONE -o $(OBJ_DIR)/ppcd.o
$(LD) -o $(BIN_DIR)/ppcd.exe -mconsole $(OBJ_DIR)/ppcd.o $(LD) -o $(BIN_DIR)/ppcd.exe -mconsole $(OBJ_DIR)/ppcd.o
tests: $(BIN_DIR) $(OBJ_DIR) $(OBJ) Src/Util/Test_Config.cpp Src/Pkgs/tinyxml2.cpp tests: $(BIN_DIR) $(OBJ_DIR) $(OBJ_DIR)/NewConfig.o $(OBJ_DIR)/ConfigBuilders.o Src/Util/Test_Config.cpp Src/Pkgs/tinyxml2.cpp
$(CXX) Src/Util/Test_Config.cpp $(CPPFLAGS) -o $(OBJ_DIR)/Test_Config.o $(CXX) Src/Util/Test_Config.cpp $(CPPFLAGS) -o $(OBJ_DIR)/Test_Config.o
$(LD) -o $(BIN_DIR)/test_config.exe -mconsole $(OBJ_DIR)/Test_Config.o $(OBJ_DIR)/Format.o $(OBJ_DIR)/NewConfig.o $(OBJ_DIR)/Logger.o $(OBJ_DIR)/tinyxml2.o $(LD) -o $(BIN_DIR)/test_config.exe -mconsole $(OBJ_DIR)/Test_Config.o $(OBJ_DIR)/Format.o $(OBJ_DIR)/NewConfig.o $(OBJ_DIR)/ConfigBuilders.o $(OBJ_DIR)/Logger.o $(OBJ_DIR)/tinyxml2.o
$(BIN_DIR): $(BIN_DIR):
mkdir $(BIN_DIR) mkdir $(BIN_DIR)

View file

@ -35,17 +35,28 @@
Output Functions Output Functions
******************************************************************************/ ******************************************************************************/
void CBlockFile::ReadString(char *str, unsigned strLen, unsigned maxLen) void CBlockFile::ReadString(std::string *str, uint32_t length)
{ {
if (NULL == fp) if (NULL == fp)
return; return;
if (strLen>maxLen) str->clear();
strLen = maxLen; //TODO: use fstream to get rid of this ugly hack
fread(str, sizeof(char), strLen, fp); bool keep_loading = true;
str[strLen] = '\0'; for (size_t i = 0; i < length; i++)
{
char c;
fread(&c, sizeof(char), 1, fp);
if (keep_loading)
{
if (!c)
keep_loading = false;
else
*str += c;
}
}
} }
unsigned CBlockFile::ReadBytes(void *data, unsigned numBytes) unsigned CBlockFile::ReadBytes(void *data, uint32_t numBytes)
{ {
if (NULL == fp) if (NULL == fp)
return 0; return 0;
@ -90,7 +101,7 @@ void CBlockFile::WriteDWord(uint32_t data)
UpdateBlockSize(); UpdateBlockSize();
} }
void CBlockFile::WriteBytes(const void *data, unsigned numBytes) void CBlockFile::WriteBytes(const void *data, uint32_t numBytes)
{ {
if (NULL == fp) if (NULL == fp)
return; return;
@ -98,24 +109,11 @@ void CBlockFile::WriteBytes(const void *data, unsigned numBytes)
UpdateBlockSize(); UpdateBlockSize();
} }
void CBlockFile::WriteBlockHeader(const char *name, const char *comment) void CBlockFile::WriteBlockHeader(const std::string &name, const std::string &comment)
{ {
unsigned nameLen, commentLen;
const char nullComment[1] = {'\0'};
if (NULL == fp) if (NULL == fp)
return; return;
if (comment == NULL)
comment = nullComment;
nameLen = strlen(name);
commentLen = strlen(comment);
if (nameLen > 1024)
nameLen = 1024;
if (commentLen > 1024)
commentLen = 1024;
// Record current block starting position // Record current block starting position
blockStartPos = ftell(fp); blockStartPos = ftell(fp);
@ -123,12 +121,10 @@ void CBlockFile::WriteBlockHeader(const char *name, const char *comment)
WriteDWord(0); // will be automatically updated as we write the file WriteDWord(0); // will be automatically updated as we write the file
// Write name and comment lengths // Write name and comment lengths
WriteDWord(nameLen+1); WriteDWord(name.size() + 1);
WriteDWord(commentLen+1); WriteDWord(comment.size() + 1);
WriteBytes(name, nameLen); Write(name);
WriteByte(0); Write(comment);
WriteBytes(comment, commentLen);
WriteByte(0);
// Record the start of the current data section // Record the start of the current data section
dataStartPos = ftell(fp); dataStartPos = ftell(fp);
@ -151,66 +147,74 @@ void CBlockFile::WriteBlockHeader(const char *name, const char *comment)
data ... Raw data (blockLength - total header size). data ... Raw data (blockLength - total header size).
******************************************************************************/ ******************************************************************************/
unsigned CBlockFile::Read(void *data, unsigned numBytes) unsigned CBlockFile::Read(void *data, uint32_t numBytes)
{ {
if (mode == 'r') if (mode == 'r')
return ReadBytes(data, numBytes); return ReadBytes(data, numBytes);
return 0; return 0;
} }
void CBlockFile::Write(const void *data, unsigned numBytes) void CBlockFile::Write(const void *data, uint32_t numBytes)
{ {
if (mode == 'w') if (mode == 'w')
WriteBytes(data, numBytes); WriteBytes(data, numBytes);
} }
void CBlockFile::NewBlock(const char *name, const char *comment) void CBlockFile::Write(const std::string &str)
{
if (mode == 'w')
WriteBytes(str.c_str(), str.length() + 1);
}
void CBlockFile::NewBlock(const std::string &name, const std::string &comment)
{ {
if (mode == 'w') if (mode == 'w')
WriteBlockHeader(name, comment); WriteBlockHeader(name, comment);
} }
bool CBlockFile::FindBlock(const char *name) bool CBlockFile::FindBlock(const std::string &name)
{ {
long int curPos = 0;
unsigned blockLen, nameLen, commentLen;
if (mode != 'r') if (mode != 'r')
return FAIL; return FAIL;
fseek(fp, 0, SEEK_SET); fseek(fp, 0, SEEK_SET);
long int curPos = 0;
while (curPos < fileSize) while (curPos < fileSize)
{ {
blockStartPos = curPos; blockStartPos = curPos;
// Read header // Read header
curPos += ReadDWord(&blockLen); uint32_t block_length;
curPos += ReadDWord(&nameLen); uint32_t name_length;
curPos += ReadDWord(&commentLen); uint32_t comment_length;
ReadString(strBuf,nameLen,1025); curPos += ReadDWord(&block_length);
curPos += ReadDWord(&name_length);
curPos += ReadDWord(&comment_length);
std::string block_name;
ReadString(&block_name, name_length);
// Is this the block we want? // Is this the block we want?
if (!strcmp(strBuf,name)) if (block_name == name)
{ {
fseek(fp, blockStartPos+12+nameLen+commentLen, SEEK_SET); // move to beginning of data fseek(fp, blockStartPos + 12 + name_length + comment_length, SEEK_SET); // move to beginning of data
dataStartPos = ftell(fp); dataStartPos = ftell(fp);
return OKAY; return OKAY;
} }
// Move to next block // Move to next block
fseek(fp, blockStartPos+blockLen, SEEK_SET); fseek(fp, blockStartPos + block_length, SEEK_SET);
curPos = blockStartPos+blockLen; curPos = blockStartPos + block_length;
if (blockLen == 0) // this would never advance if (block_length == 0) // this would never advance
break; break;
} }
return FAIL; return FAIL;
} }
bool CBlockFile::Create(const char *file, const char *headerName, const char *comment) bool CBlockFile::Create(const std::string &file, const std::string &headerName, const std::string &comment)
{ {
fp = fopen(file, "wb"); fp = fopen(file.c_str(), "wb");
if (NULL == fp) if (NULL == fp)
return FAIL; return FAIL;
mode = 'w'; mode = 'w';
@ -218,9 +222,9 @@ bool CBlockFile::Create(const char *file, const char *headerName, const char *co
return OKAY; return OKAY;
} }
bool CBlockFile::Load(const char *file) bool CBlockFile::Load(const std::string &file)
{ {
fp = fopen(file, "rb"); fp = fopen(file.c_str(), "rb");
if (NULL == fp) if (NULL == fp)
return FAIL; return FAIL;
mode = 'r'; mode = 'r';

View file

@ -57,7 +57,7 @@ public:
* Number of bytes read. If not the same as numBytes, an error * Number of bytes read. If not the same as numBytes, an error
* occurred. * occurred.
*/ */
unsigned Read(void *data, unsigned numBytes); unsigned Read(void *data, uint32_t numBytes);
/* /*
* FindBlock(name): * FindBlock(name):
@ -71,7 +71,7 @@ public:
* Returns: * Returns:
* OKAY if found, FAIL if unable to locate. * OKAY if found, FAIL if unable to locate.
*/ */
bool FindBlock(const char *name); bool FindBlock(const std::string &name);
/* /*
* Write(data, numBytes): * Write(data, numBytes):
@ -83,7 +83,18 @@ public:
* data Data to write. * data Data to write.
* numBytes Number of bytes to write. * numBytes Number of bytes to write.
*/ */
void Write(const void *data, unsigned numBytes); void Write(const void *data, uint32_t numBytes);
/*
* Write(str):
*
* Outputs string (including null terminator) at the current file pointer
* position. Updates the block header appropriately.
*
* Parameters:
* str String to write.
*/
void Write(const std::string &str);
/* /*
* NewBlock(name, comment): * NewBlock(name, comment):
@ -95,7 +106,7 @@ public:
* name Block name. Must be unique and not NULL. * name Block name. Must be unique and not NULL.
* comment Comment string to embed in the block header. * comment Comment string to embed in the block header.
*/ */
void NewBlock(const char *title, const char *comment); void NewBlock(const std::string &title, const std::string &comment);
/* /*
* Create(file, headerName, comment): * Create(file, headerName, comment):
@ -113,7 +124,7 @@ public:
* Returns: * Returns:
* OKAY if successfully opened, otherwise FAIL. * OKAY if successfully opened, otherwise FAIL.
*/ */
bool Create(const char *file, const char *headerName, const char *comment); bool Create(const std::string &file, const std::string &headerName, const std::string &comment);
/* /*
* Load(file): * Load(file):
@ -129,7 +140,7 @@ public:
* subsequent operations will be silently ignored (reads will return * subsequent operations will be silently ignored (reads will return
* 0's). Write commands will be ignored. * 0's). Write commands will be ignored.
*/ */
bool Load(const char *file); bool Load(const std::string &file);
/* /*
* Close(void): * Close(void):
@ -149,17 +160,16 @@ public:
private: private:
// Helper functions // Helper functions
void ReadString(char *str, unsigned strLen, unsigned maxLen); void ReadString(std::string *str, uint32_t length);
unsigned ReadBytes(void *data, unsigned numBytes); unsigned ReadBytes(void *data, uint32_t numBytes);
unsigned ReadDWord(uint32_t *data); unsigned ReadDWord(uint32_t *data);
void UpdateBlockSize(void); void UpdateBlockSize(void);
void WriteByte(uint8_t data); void WriteByte(uint8_t data);
void WriteDWord(uint32_t data); void WriteDWord(uint32_t data);
void WriteBytes(const void *data, unsigned numBytes); void WriteBytes(const void *data, uint32_t numBytes);
void WriteBlockHeader(const char *name, const char *comment); void WriteBlockHeader(const std::string &name, const std::string &comment);
// File state data // File state data
char strBuf[1026]; // buffers up to a 1024-character string, its terminator, and an extra terminator (just in case)
FILE *fp; FILE *fp;
int mode; // 'r' for read, 'w' for write int mode; // 'r' for read, 'w' for write
long int fileSize; // size of file in bytes long int fileSize; // size of file in bytes

View file

@ -1,31 +0,0 @@
/**
** Supermodel
** A Sega Model 3 Arcade Emulator.
** Copyright 2011 Bart Trzynadlowski, Nik Henson
**
** 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;

View file

@ -1,71 +0,0 @@
/**
** Supermodel
** A Sega Model 3 Arcade Emulator.
** Copyright 2011 Bart Trzynadlowski, Nik Henson
**
** 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 Legacy3D::CLegacy3DConfig, public CModel3Config, public CSoundBoardConfig, public CDSBConfig, public CDriveBoardConfig
{
};
/*
* g_Config:
*
* Program-wide configuration settings object.
*/
extern CConfig g_Config;
#endif // INCLUDED_CONFIG_H

View file

@ -514,7 +514,7 @@ namespace Debugger
} }
else if (CheckToken(token, "caip", "configallinputs")) // configallinputs else if (CheckToken(token, "caip", "configallinputs")) // configallinputs
{ {
m_inputs->ConfigureInputs(m_model3->GetGameInfo()); m_inputs->ConfigureInputs(&m_model3->GetGame());
return false; return false;
} }
// //
@ -544,7 +544,7 @@ namespace Debugger
bool CSupermodelDebugger::InputIsValid(::CInput *input) bool CSupermodelDebugger::InputIsValid(::CInput *input)
{ {
return input->IsUIInput() || (input->gameFlags & m_model3->GetGameInfo()->inputFlags); return input->IsUIInput() || (input->gameFlags & m_model3->GetGame().inputs);
} }
void CSupermodelDebugger::ListInputs() void CSupermodelDebugger::ListInputs()
@ -599,14 +599,14 @@ namespace Debugger
CConsoleDebugger::Attached(); CConsoleDebugger::Attached();
char fileName[25]; char fileName[25];
sprintf(fileName, "Debug/%s.ds", m_model3->GetGameInfo()->id); sprintf(fileName, "Debug/%s.ds", m_model3->GetGame().name.c_str());
LoadState(fileName); LoadState(fileName);
} }
void CSupermodelDebugger::Detaching() void CSupermodelDebugger::Detaching()
{ {
char fileName[25]; char fileName[25];
sprintf(fileName, "Debug/%s.ds", m_model3->GetGameInfo()->id); sprintf(fileName, "Debug/%s.ds", m_model3->GetGame().name.c_str());
SaveState(fileName); SaveState(fileName);
CConsoleDebugger::Detaching(); CConsoleDebugger::Detaching();

View file

@ -799,7 +799,7 @@ void CLegacy3D::DescendNodePtr(UINT32 nodeAddr)
} }
// Draws viewports of the given priority // Draws viewports of the given priority
void CLegacy3D::RenderViewport(UINT32 addr, int pri) void CLegacy3D::RenderViewport(UINT32 addr, int pri, bool wideScreen)
{ {
static const GLfloat color[8][3] = { static const GLfloat color[8][3] = {
{ 0.0, 0.0, 0.0 }, // off { 0.0, 0.0, 0.0 }, // off
@ -823,7 +823,7 @@ void CLegacy3D::RenderViewport(UINT32 addr, int pri)
if (nextAddr == 0) // memory probably hasn't been set up yet, abort if (nextAddr == 0) // memory probably hasn't been set up yet, abort
return; return;
if (nextAddr != 0x01000000) if (nextAddr != 0x01000000)
RenderViewport(nextAddr, pri); RenderViewport(nextAddr, pri, wideScreen);
// Skip disabled viewports // Skip disabled viewports
//if ((vpnode[0] & 0x20) != 0) //if ((vpnode[0] & 0x20) != 0)
@ -849,7 +849,7 @@ void CLegacy3D::RenderViewport(UINT32 addr, int pri)
// Set up viewport and projection (TO-DO: near and far clipping) // Set up viewport and projection (TO-DO: near and far clipping)
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
if (g_Config.wideScreen && (vpX==0) && (vpWidth>=495) && (vpY==0) && (vpHeight >= 383)) // only expand viewports that occupy whole screen if (wideScreen && (vpX==0) && (vpWidth>=495) && (vpY==0) && (vpHeight >= 383)) // only expand viewports that occupy whole screen
{ {
// Wide screen hack only modifies X axis and not the Y FOV // Wide screen hack only modifies X axis and not the Y FOV
viewportX = 0; viewportX = 0;
@ -958,6 +958,8 @@ void CLegacy3D::RenderViewport(UINT32 addr, int pri)
void CLegacy3D::RenderFrame(void) void CLegacy3D::RenderFrame(void)
{ {
bool wideScreen = m_config["WideScreen"].ValueAs<bool>();
// Begin frame // Begin frame
ClearErrors(); // must be cleared each frame ClearErrors(); // must be cleared each frame
@ -1009,7 +1011,7 @@ void CLegacy3D::RenderFrame(void)
//ClearModelCache(&PolyCache); //ClearModelCache(&PolyCache);
ClearDisplayList(&PolyCache); ClearDisplayList(&PolyCache);
ClearDisplayList(&VROMCache); ClearDisplayList(&VROMCache);
RenderViewport(0x800000,pri); RenderViewport(0x800000,pri,wideScreen);
DrawDisplayList(&VROMCache, POLY_STATE_NORMAL); DrawDisplayList(&VROMCache, POLY_STATE_NORMAL);
DrawDisplayList(&PolyCache, POLY_STATE_NORMAL); DrawDisplayList(&PolyCache, POLY_STATE_NORMAL);
DrawDisplayList(&VROMCache, POLY_STATE_ALPHA); DrawDisplayList(&VROMCache, POLY_STATE_ALPHA);
@ -1058,9 +1060,9 @@ void CLegacy3D::AttachMemory(const UINT32 *cullingRAMLoPtr, const UINT32 *cullin
DebugLog("Legacy3D attached Real3D memory regions\n"); DebugLog("Legacy3D attached Real3D memory regions\n");
} }
void CLegacy3D::SetStep(int stepID) void CLegacy3D::SetStepping(int stepping)
{ {
step = stepID; step = stepping;
if ((step!=0x10) && (step!=0x15) && (step!=0x20) && (step!=0x21)) if ((step!=0x10) && (step!=0x15) && (step!=0x20) && (step!=0x21))
{ {
@ -1124,12 +1126,12 @@ bool CLegacy3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned
// Get upper limit for number of texture maps to use from max number of texture units supported by video card // Get upper limit for number of texture maps to use from max number of texture units supported by video card
GLint glMaxTexUnits; GLint glMaxTexUnits;
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &glMaxTexUnits); glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &glMaxTexUnits);
int maxTexMaps = std::max<int>(1, std::min<int>(g_Config.maxTexMaps, glMaxTexUnits)); int maxTexMaps = std::max<int>(1, std::min<int>(m_config["MaxTexMaps"].ValueAsDefault<int>(9), glMaxTexUnits));
// Get upper limit for extent of texture maps to use from max texture size supported by video card // Get upper limit for extent of texture maps to use from max texture size supported by video card
GLint maxTexSize; GLint maxTexSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
int mapExtent = std::max<int>(1, std::min<unsigned>(g_Config.maxTexMapExtent, maxTexSize / 2048)); int mapExtent = std::max<int>(1, std::min<unsigned>(m_config["MaxTexMapExtent"].ValueAsDefault<int>(4), maxTexSize / 2048));
int mapSize = 2048 * mapExtent; int mapSize = 2048 * mapExtent;
while (mapExtent > 1) while (mapExtent > 1)
{ {
@ -1147,10 +1149,8 @@ bool CLegacy3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned
} }
// Load shaders, using multi-sheet shader if requested. // Load shaders, using multi-sheet shader if requested.
const char *vsFile = g_Config.vertexShaderFile.size() ? g_Config.vertexShaderFile.c_str() : NULL; const char *fragmentShaderSource = (m_config["MultiTexture"].ValueAs<bool>() ? fragmentShaderMultiSheetSource : fragmentShaderSingleSheetSource); // single texture shader
const char *fsFile = g_Config.fragmentShaderFile.size() ? g_Config.fragmentShaderFile.c_str() : NULL; if (OKAY != LoadShaderProgram(&shaderProgram,&vertexShader,&fragmentShader,m_config["VertexShader"].ValueAs<std::string>(),m_config["FragmentShader"].ValueAs<std::string>(),vertexShaderSource,fragmentShaderSource))
const char *fragmentShaderSource = (g_Config.multiTexture ? fragmentShaderMultiSheetSource : fragmentShaderSingleSheetSource); // single texture shader
if (OKAY != LoadShaderProgram(&shaderProgram,&vertexShader,&fragmentShader,vsFile,fsFile,vertexShaderSource,fragmentShaderSource))
return FAIL; return FAIL;
// Try locating default "textureMap" uniform in shader program // Try locating default "textureMap" uniform in shader program
@ -1291,7 +1291,8 @@ bool CLegacy3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned
return OKAY; return OKAY;
} }
CLegacy3D::CLegacy3D(void) CLegacy3D::CLegacy3D(const Util::Config::Node &config)
: m_config(config)
{ {
cullingRAMLo = NULL; cullingRAMLo = NULL;
cullingRAMHi = NULL; cullingRAMHi = NULL;

View file

@ -31,6 +31,7 @@
#include "Graphics/IRender3D.h" #include "Graphics/IRender3D.h"
#include "Pkgs/glew.h" #include "Pkgs/glew.h"
#include "Util/NewConfig.h"
namespace Legacy3D { namespace Legacy3D {
@ -223,30 +224,6 @@ struct TexSheet
CLegacy3D Classes CLegacy3D Classes
******************************************************************************/ ******************************************************************************/
/*
* CLegacy3DConfig:
*
* Settings used by CLegacy3D.
*/
class CLegacy3DConfig
{
public:
string vertexShaderFile; // path to vertex shader or "" to use internal shader
string fragmentShaderFile; // fragment shader
unsigned maxTexMaps; // maximum number of texture maps to use (1-9)
unsigned maxTexMapExtent; // maximum extent of texture maps (where num of tex sheets per map = extent ^ 2)
bool multiTexture; // if enabled and no external fragment shader, select internal shader w/ multiple texture sheet support
// Defaults
CLegacy3DConfig(void)
{
// strings will be clear to begin with
maxTexMaps = 9;
maxTexMapExtent = 4;
multiTexture = false;
}
};
/* /*
* CLegacy3D: * CLegacy3D:
* *
@ -314,17 +291,17 @@ public:
const UINT32 *vromPtr, const UINT16 *textureRAMPtr); const UINT32 *vromPtr, const UINT16 *textureRAMPtr);
/* /*
* SetStep(stepID): * SetStepping(stepping):
* *
* Sets the Model 3 hardware stepping, which also determines the Real3D * Sets the Model 3 hardware stepping, which also determines the Real3D
* functionality. The default is Step 1.0. This should be called prior to * functionality. The default is Step 1.0. This should be called prior to
* any other emulation functions and after Init(). * any other emulation functions and after Init().
* *
* Parameters: * Parameters:
* stepID 0x10 for Step 1.0, 0x15 for Step 1.5, 0x20 for Step 2.0, * stepping 0x10 for Step 1.0, 0x15 for Step 1.5, 0x20 for Step 2.0, or
* or 0x21 for Step 2.1. Anything else defaults to 1.0. * 0x21 for Step 2.1. Anything else defaults to 1.0.
*/ */
void SetStep(int stepID); void SetStepping(int stepping);
/* /*
* Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes): * Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes):
@ -355,16 +332,19 @@ public:
* CLegacy3D(void): * CLegacy3D(void):
* ~CLegacy3D(void): * ~CLegacy3D(void):
* *
* Parameters:
* config Configuration object.
*
* Constructor and destructor. * Constructor and destructor.
*/ */
CLegacy3D(void); CLegacy3D(const Util::Config::Node &config);
~CLegacy3D(void); ~CLegacy3D(void);
private: private:
/* /*
* Private Members * Private Members
*/ */
// Real3D address translation // Real3D address translation
const UINT32 *TranslateCullingAddress(UINT32 addr); const UINT32 *TranslateCullingAddress(UINT32 addr);
const UINT32 *TranslateModelAddress(UINT32 addr); const UINT32 *TranslateModelAddress(UINT32 addr);
@ -397,7 +377,7 @@ private:
void DescendCullingNode(UINT32 addr); void DescendCullingNode(UINT32 addr);
void DescendPointerList(UINT32 addr); void DescendPointerList(UINT32 addr);
void DescendNodePtr(UINT32 nodeAddr); void DescendNodePtr(UINT32 nodeAddr);
void RenderViewport(UINT32 addr, int pri); void RenderViewport(UINT32 addr, int pri, bool wideScreen);
// In-frame error reporting // In-frame error reporting
bool ErrorLocalVertexOverflow(void); bool ErrorLocalVertexOverflow(void);
@ -407,6 +387,8 @@ private:
/* /*
* Data * Data
*/ */
const Util::Config::Node &m_config;
// Stepping // Stepping
int step; int step;

View file

@ -35,9 +35,9 @@ void CNew3D::AttachMemory(const UINT32 *cullingRAMLoPtr, const UINT32 *cullingRA
m_textureRAM = textureRAMPtr; m_textureRAM = textureRAMPtr;
} }
void CNew3D::SetStep(int stepID) void CNew3D::SetStepping(int stepping)
{ {
m_step = stepID; m_step = stepping;
if ((m_step != 0x10) && (m_step != 0x15) && (m_step != 0x20) && (m_step != 0x21)) { if ((m_step != 0x10) && (m_step != 0x15) && (m_step != 0x20) && (m_step != 0x21)) {
m_step = 0x10; m_step = 0x10;

View file

@ -104,17 +104,17 @@ public:
const UINT32 *vromPtr, const UINT16 *textureRAMPtr); const UINT32 *vromPtr, const UINT16 *textureRAMPtr);
/* /*
* SetStep(stepID): * SetStepping(stepping):
* *
* Sets the Model 3 hardware stepping, which also determines the Real3D * Sets the Model 3 hardware stepping, which also determines the Real3D
* functionality. The default is Step 1.0. This should be called prior to * functionality. The default is Step 1.0. This should be called prior to
* any other emulation functions and after Init(). * any other emulation functions and after Init().
* *
* Parameters: * Parameters:
* stepID 0x10 for Step 1.0, 0x15 for Step 1.5, 0x20 for Step 2.0, * stepping 0x10 for Step 1.0, 0x15 for Step 1.5, 0x20 for Step 2.0, or
* or 0x21 for Step 2.1. Anything else defaults to 1.0. * 0x21 for Step 2.1. Anything else defaults to 1.0.
*/ */
void SetStep(int stepID); void SetStepping(int stepping);
/* /*
* Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes): * Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes):

View file

@ -80,7 +80,7 @@ void R3DScrollFog::DrawScrollFog(float r, float g, float b, float a)
void R3DScrollFog::AllocResources() void R3DScrollFog::AllocResources()
{ {
bool success = LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, nullptr, nullptr, vertexShaderFog, fragmentShaderFog); bool success = LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, std::string(), std::string(), vertexShaderFog, fragmentShaderFog);
m_locMVP = glGetUniformLocation(m_shaderProgram, "mvp"); m_locMVP = glGetUniformLocation(m_shaderProgram, "mvp");
m_locFogColour = glGetUniformLocation(m_shaderProgram, "fogColour"); m_locFogColour = glGetUniformLocation(m_shaderProgram, "fogColour");

View file

@ -195,7 +195,7 @@ bool R3DShader::LoadShader(const char* vertexShader, const char* fragmentShader)
fShader = fragmentShaderBasic; fShader = fragmentShaderBasic;
} }
success = LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, nullptr, nullptr, vShader, fShader); success = LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, std::string(), std::string(), vShader, fShader);
m_locTexture1 = glGetUniformLocation(m_shaderProgram, "tex1"); m_locTexture1 = glGetUniformLocation(m_shaderProgram, "tex1");
m_locTexture2 = glGetUniformLocation(m_shaderProgram, "tex2"); m_locTexture2 = glGetUniformLocation(m_shaderProgram, "tex2");

View file

@ -638,7 +638,7 @@ void CRender2D::AttachVRAM(const uint8_t *vramPtr)
bool CRender2D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes) bool CRender2D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes)
{ {
// Load shaders // Load shaders
if (OKAY != LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, 0, 0, s_vertexShaderSource, s_fragmentShaderSource)) if (OKAY != LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, std::string(), std::string(), s_vertexShaderSource, s_fragmentShaderSource))
return FAIL; return FAIL;
// Get locations of the uniforms // Get locations of the uniforms

View file

@ -82,7 +82,7 @@ static char *LoadShaderSource(const char *file)
return buf; return buf;
} }
bool LoadShaderProgram(GLuint *shaderProgramPtr, GLuint *vertexShaderPtr, GLuint *fragmentShaderPtr, const char *vsFile, const char *fsFile, const char *vsString, const char *fsString) bool LoadShaderProgram(GLuint *shaderProgramPtr, GLuint *vertexShaderPtr, GLuint *fragmentShaderPtr, std::string vsFile, std::string fsFile, const char *vsString, const char *fsString)
{ {
char infoLog[2048]; char infoLog[2048];
const char *vsSource, *fsSource; // source code const char *vsSource, *fsSource; // source code
@ -91,12 +91,12 @@ bool LoadShaderProgram(GLuint *shaderProgramPtr, GLuint *vertexShaderPtr, GLuint
bool ret = OKAY; bool ret = OKAY;
// Load shaders from files if specified // Load shaders from files if specified
if (vsFile != NULL) if (!vsFile.empty())
vsSource = LoadShaderSource(vsFile); vsSource = LoadShaderSource(vsFile.c_str());
else else
vsSource = vsString; vsSource = vsString;
if (fsFile != NULL) if (!fsFile.empty())
fsSource = LoadShaderSource(fsFile); fsSource = LoadShaderSource(fsFile.c_str());
else else
fsSource = fsString; fsSource = fsString;
if (vsSource == NULL || fsSource == NULL) if (vsSource == NULL || fsSource == NULL)
@ -161,9 +161,9 @@ bool LoadShaderProgram(GLuint *shaderProgramPtr, GLuint *vertexShaderPtr, GLuint
// Clean up and quit // Clean up and quit
Quit: Quit:
if ((vsSource != NULL) && (vsFile != NULL)) // loaded from file, must delete if ((vsSource != NULL) && !vsFile.empty()) // loaded from file, must delete
delete [] vsSource; delete [] vsSource;
if ((fsSource != NULL) && (fsFile != NULL)) // "" if ((fsSource != NULL) && !fsFile.empty()) // ""
delete [] fsSource; delete [] fsSource;
return ret; return ret;
} }

View file

@ -29,6 +29,7 @@
#define INCLUDED_SHADER_H #define INCLUDED_SHADER_H
#include "Pkgs/glew.h" #include "Pkgs/glew.h"
#include <string>
/* /*
* LoadShaderProgram(shaderProgramPtr, vertexShaderPtr, fragmentShaderPtr, * LoadShaderProgram(shaderProgramPtr, vertexShaderPtr, fragmentShaderPtr,
@ -52,8 +53,8 @@
* OKAY is successfully loaded, otherwise FAIL. Prints own error messages. * OKAY is successfully loaded, otherwise FAIL. Prints own error messages.
*/ */
extern bool LoadShaderProgram(GLuint *shaderProgramPtr, GLuint *vertexShaderPtr, extern bool LoadShaderProgram(GLuint *shaderProgramPtr, GLuint *vertexShaderPtr,
GLuint *fragmentShaderPtr, const char *vsFile, GLuint *fragmentShaderPtr, std::string vsFile,
const char *fsFile, const char *vsString, std::string fsFile, const char *vsString,
const char *fsString); const char *fsString);
/* /*

View file

@ -83,29 +83,29 @@ const char* CInput::GetInputGroup()
{ {
switch (gameFlags) switch (gameFlags)
{ {
case GAME_INPUT_UI: return "User Interface Controls"; case Game::INPUT_UI: return "User Interface Controls";
case GAME_INPUT_COMMON: return "Common Controls"; case Game::INPUT_COMMON: return "Common Controls";
case GAME_INPUT_JOYSTICK1: // Fall through to below case Game::INPUT_JOYSTICK1: // Fall through to below
case GAME_INPUT_JOYSTICK2: return "4-Way Joysticks"; case Game::INPUT_JOYSTICK2: return "4-Way Joysticks";
case GAME_INPUT_FIGHTING: return "Fighting Game Buttons"; case Game::INPUT_FIGHTING: return "Fighting Game Buttons";
case GAME_INPUT_SPIKEOUT: return "Spikeout Buttons"; case Game::INPUT_SPIKEOUT: return "Spikeout Buttons";
case GAME_INPUT_SOCCER: return "Virtua Striker Buttons"; case Game::INPUT_SOCCER: return "Virtua Striker Buttons";
case GAME_INPUT_VEHICLE: return "Racing Game Steering Controls"; case Game::INPUT_VEHICLE: return "Racing Game Steering Controls";
case GAME_INPUT_SHIFT4: return "Racing Game Gear 4-Way Shift"; case Game::INPUT_SHIFT4: return "Racing Game Gear 4-Way Shift";
case GAME_INPUT_SHIFTUPDOWN: return "Racing Game Gear Up/Down Shift"; case Game::INPUT_SHIFTUPDOWN: return "Racing Game Gear Up/Down Shift";
case GAME_INPUT_VR4: return "Racing Game 4 VR View Buttons"; case Game::INPUT_VR4: return "Racing Game 4 VR View Buttons";
case GAME_INPUT_VIEWCHANGE: return "Racing Game View Change"; case Game::INPUT_VIEWCHANGE: return "Racing Game View Change";
case GAME_INPUT_HANDBRAKE: return "Racing Game Handbrake"; case Game::INPUT_HANDBRAKE: return "Racing Game Handbrake";
case GAME_INPUT_HARLEY: return "Harley Davidson Controls"; case Game::INPUT_HARLEY: return "Harley Davidson Controls";
case GAME_INPUT_TWIN_JOYSTICKS: return "Virtual On Controls"; case Game::INPUT_TWIN_JOYSTICKS: return "Virtual On Controls";
case GAME_INPUT_ANALOG_JOYSTICK: return "Analog Joystick"; case Game::INPUT_ANALOG_JOYSTICK: return "Analog Joystick";
case GAME_INPUT_GUN1: // Fall through to below case Game::INPUT_GUN1: // Fall through to below
case GAME_INPUT_GUN2: return "Light Guns"; case Game::INPUT_GUN2: return "Light Guns";
case GAME_INPUT_ANALOG_GUN1: // Fall through to below case Game::INPUT_ANALOG_GUN1: // Fall through to below
case GAME_INPUT_ANALOG_GUN2: return "Analog Guns"; case Game::INPUT_ANALOG_GUN2: return "Analog Guns";
case GAME_INPUT_SKI: return "Ski Controls"; case Game::INPUT_SKI: return "Ski Controls";
case GAME_INPUT_MAGTRUCK: return "Magical Truck Controls"; case Game::INPUT_MAGTRUCK: return "Magical Truck Controls";
case GAME_INPUT_FISHING: return "Fishing Controls"; case Game::INPUT_FISHING: return "Fishing Controls";
default: return "Misc"; default: return "Misc";
} }
} }
@ -147,6 +147,38 @@ void CInput::ResetToDefaultMapping()
SetMapping(m_defaultMapping); SetMapping(m_defaultMapping);
} }
void CInput::LoadFromConfig(const Util::Config::Node &config)
{
// See if input is configurable
if (IsConfigurable())
{
// If so, check INI file for mapping string
string key("Input");
key.append(id);
string mapping;
auto *node = config.TryGet(key);
if (node)
{
// If found, then set mapping string
mapping = node->ValueAs<std::string>();
SetMapping(mapping.c_str());
return;
}
}
// If input has not been configured, then force recreation of source anyway since input system settings may have changed
CreateSource();
}
void CInput::StoreToConfig(Util::Config::Node *config)
{
if (!IsConfigurable())
return;
string key("Input");
key.append(id);
config->Set(key, m_mapping);
}
void CInput::ReadFromINIFile(CINIFile *ini, const char *section) void CInput::ReadFromINIFile(CINIFile *ini, const char *section)
{ {
// See if input is configurable // See if input is configurable

View file

@ -23,21 +23,20 @@
* Input.h * Input.h
* *
* Header file for base input class, CInput, defining an input source. Also * Header file for base input class, CInput, defining an input source. Also
* defines GAME_INPUT_UI. * defines Game::INPUT_UI.
*/ */
#ifndef INCLUDED_INPUT_H #ifndef INCLUDED_INPUT_H
#define INCLUDED_INPUT_H #define INCLUDED_INPUT_H
#include "Types.h" #include "Types.h"
#include "Game.h"
#include "Util/NewConfig.h"
class CInputSource; class CInputSource;
class CInputSystem; class CInputSystem;
class CINIFile; class CINIFile;
// Special game input flag for UI controls
#define GAME_INPUT_UI 0
// Flags for inputs // Flags for inputs
#define INPUT_FLAGS_SWITCH 0x0001 #define INPUT_FLAGS_SWITCH 0x0001
#define INPUT_FLAGS_ANALOG 0x0002 #define INPUT_FLAGS_ANALOG 0x0002
@ -152,13 +151,15 @@ public:
void ResetToDefaultMapping(); void ResetToDefaultMapping();
/* /*
* Reads the input's mapping(s) from the given INI file, as well as any other settings. * Loads the input's mapping(s) from the given config object, as well as any other settings.
*/ */
virtual void LoadFromConfig(const Util::Config::Node &config);
virtual void ReadFromINIFile(CINIFile *ini, const char *section); virtual void ReadFromINIFile(CINIFile *ini, const char *section);
/* /*
* Writes the current input mapping(s) to the given INI file, as well as any other settings. * Stores the current input mapping(s) to the given config object, as well as any other settings.
*/ */
virtual void StoreToConfig(Util::Config::Node *config);
virtual void WriteToINIFile(CINIFile *ini, const char *section); virtual void WriteToINIFile(CINIFile *ini, const char *section);
void InputSystemChanged(); void InputSystemChanged();
@ -207,13 +208,13 @@ public:
inline bool CInput::IsUIInput() inline bool CInput::IsUIInput()
{ {
return gameFlags == GAME_INPUT_UI; return gameFlags == Game::INPUT_UI;
} }
inline bool CInput::IsConfigurable() inline bool CInput::IsConfigurable()
{ {
// All inputs except UI and virtual ones can be configured by the user // All inputs except UI and virtual ones can be configured by the user
return (gameFlags != GAME_INPUT_UI) && !(flags & INPUT_FLAGS_VIRTUAL); return (gameFlags != Game::INPUT_UI) && !(flags & INPUT_FLAGS_VIRTUAL);
} }
inline bool CInput::IsVirtual() inline bool CInput::IsVirtual()

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -27,6 +27,7 @@
*/ */
#include "Supermodel.h" #include "Supermodel.h"
#include "Game.h"
#include <stdarg.h> #include <stdarg.h>
#include <vector> #include <vector>
@ -34,240 +35,241 @@
#include <iostream> #include <iostream>
using namespace std; using namespace std;
CInputs::CInputs(CInputSystem *system) : m_system(system) CInputs::CInputs(CInputSystem *system)
: m_system(system)
{ {
// UI controls are hard coded here, everything else is initialized to NONE so that it can be loaded from // UI controls are hard coded here, everything else is initialized to NONE so that it can be loaded from
// the config file. // the config file.
// UI Controls // UI Controls
uiExit = AddSwitchInput("UIExit", "Exit UI", GAME_INPUT_UI, "KEY_ESCAPE"); uiExit = AddSwitchInput("UIExit", "Exit UI", Game::INPUT_UI, "KEY_ESCAPE");
uiReset = AddSwitchInput("UIReset", "Reset", GAME_INPUT_UI, "KEY_ALT+KEY_R"); uiReset = AddSwitchInput("UIReset", "Reset", Game::INPUT_UI, "KEY_ALT+KEY_R");
uiPause = AddSwitchInput("UIPause", "Pause", GAME_INPUT_UI, "KEY_ALT+KEY_P"); uiPause = AddSwitchInput("UIPause", "Pause", Game::INPUT_UI, "KEY_ALT+KEY_P");
uiFullScreen = AddSwitchInput("UIFullScreen", "Toggle Fullscreen", GAME_INPUT_UI, "KEY_ALT+KEY_RETURN"); uiFullScreen = AddSwitchInput("UIFullScreen", "Toggle Fullscreen", Game::INPUT_UI, "KEY_ALT+KEY_RETURN");
uiSaveState = AddSwitchInput("UISaveState", "Save State", GAME_INPUT_UI, "KEY_F5"); uiSaveState = AddSwitchInput("UISaveState", "Save State", Game::INPUT_UI, "KEY_F5");
uiChangeSlot = AddSwitchInput("UIChangeSlot", "Change Save Slot", GAME_INPUT_UI, "KEY_F6"); uiChangeSlot = AddSwitchInput("UIChangeSlot", "Change Save Slot", Game::INPUT_UI, "KEY_F6");
uiLoadState = AddSwitchInput("UILoadState", "Load State", GAME_INPUT_UI, "KEY_F7"); uiLoadState = AddSwitchInput("UILoadState", "Load State", Game::INPUT_UI, "KEY_F7");
uiMusicVolUp = AddSwitchInput("UIMusicVolUp", "Increase Music Volume", GAME_INPUT_UI, "KEY_F10"); uiMusicVolUp = AddSwitchInput("UIMusicVolUp", "Increase Music Volume", Game::INPUT_UI, "KEY_F10");
uiMusicVolDown = AddSwitchInput("UIMusicVolDown", "Decrease Music Volume", GAME_INPUT_UI, "KEY_F9"); uiMusicVolDown = AddSwitchInput("UIMusicVolDown", "Decrease Music Volume", Game::INPUT_UI, "KEY_F9");
uiSoundVolUp = AddSwitchInput("UISoundVolUp", "Increase Sound Volume", GAME_INPUT_UI, "KEY_F12"); uiSoundVolUp = AddSwitchInput("UISoundVolUp", "Increase Sound Volume", Game::INPUT_UI, "KEY_F12");
uiSoundVolDown = AddSwitchInput("UISoundVolDown", "Decrease Sound Volume", GAME_INPUT_UI, "KEY_F11"); uiSoundVolDown = AddSwitchInput("UISoundVolDown", "Decrease Sound Volume", Game::INPUT_UI, "KEY_F11");
uiClearNVRAM = AddSwitchInput("UIClearNVRAM", "Clear NVRAM", GAME_INPUT_UI, "KEY_ALT+KEY_N"); uiClearNVRAM = AddSwitchInput("UIClearNVRAM", "Clear NVRAM", Game::INPUT_UI, "KEY_ALT+KEY_N");
uiSelectCrosshairs = AddSwitchInput("UISelectCrosshairs", "Select Crosshairs", GAME_INPUT_UI, "KEY_ALT+KEY_I"); uiSelectCrosshairs = AddSwitchInput("UISelectCrosshairs", "Select Crosshairs", Game::INPUT_UI, "KEY_ALT+KEY_I");
uiToggleFrLimit = AddSwitchInput("UIToggleFrameLimit", "Toggle Frame Limiting", GAME_INPUT_UI, "KEY_ALT+KEY_T"); uiToggleFrLimit = AddSwitchInput("UIToggleFrameLimit", "Toggle Frame Limiting", Game::INPUT_UI, "KEY_ALT+KEY_T");
uiDumpInpState = AddSwitchInput("UIDumpInputState", "Dump Input State", GAME_INPUT_UI, "KEY_ALT+KEY_U"); uiDumpInpState = AddSwitchInput("UIDumpInputState", "Dump Input State", Game::INPUT_UI, "KEY_ALT+KEY_U");
uiDumpTimings = AddSwitchInput("UIDumpTimings", "Dump Frame Timings", GAME_INPUT_UI, "KEY_ALT+KEY_O"); uiDumpTimings = AddSwitchInput("UIDumpTimings", "Dump Frame Timings", Game::INPUT_UI, "KEY_ALT+KEY_O");
#ifdef SUPERMODEL_DEBUGGER #ifdef SUPERMODEL_DEBUGGER
uiEnterDebugger = AddSwitchInput("UIEnterDebugger", "Enter Debugger", GAME_INPUT_UI, "KEY_ALT+KEY_B"); uiEnterDebugger = AddSwitchInput("UIEnterDebugger", "Enter Debugger", Game::INPUT_UI, "KEY_ALT+KEY_B");
#endif #endif
// Common Controls // Common Controls
start[0] = AddSwitchInput("Start1", "P1 Start", GAME_INPUT_COMMON, "NONE"); start[0] = AddSwitchInput("Start1", "P1 Start", Game::INPUT_COMMON, "NONE");
start[1] = AddSwitchInput("Start2", "P2 Start", GAME_INPUT_COMMON, "NONE"); start[1] = AddSwitchInput("Start2", "P2 Start", Game::INPUT_COMMON, "NONE");
coin[0] = AddSwitchInput("Coin1", "P1 Coin", GAME_INPUT_COMMON, "NONE"); coin[0] = AddSwitchInput("Coin1", "P1 Coin", Game::INPUT_COMMON, "NONE");
coin[1] = AddSwitchInput("Coin2", "P2 Coin", GAME_INPUT_COMMON, "NONE"); coin[1] = AddSwitchInput("Coin2", "P2 Coin", Game::INPUT_COMMON, "NONE");
service[0] = AddSwitchInput("ServiceA", "Service A", GAME_INPUT_COMMON, "NONE"); service[0] = AddSwitchInput("ServiceA", "Service A", Game::INPUT_COMMON, "NONE");
service[1] = AddSwitchInput("ServiceB", "Service B", GAME_INPUT_COMMON, "NONE"); service[1] = AddSwitchInput("ServiceB", "Service B", Game::INPUT_COMMON, "NONE");
test[0] = AddSwitchInput("TestA", "Test A", GAME_INPUT_COMMON, "NONE"); test[0] = AddSwitchInput("TestA", "Test A", Game::INPUT_COMMON, "NONE");
test[1] = AddSwitchInput("TestB", "Test B", GAME_INPUT_COMMON, "NONE"); test[1] = AddSwitchInput("TestB", "Test B", Game::INPUT_COMMON, "NONE");
// 4-Way Joysticks // 4-Way Joysticks
up[0] = AddSwitchInput("JoyUp", "P1 Joystick Up", GAME_INPUT_JOYSTICK1, "NONE"); up[0] = AddSwitchInput("JoyUp", "P1 Joystick Up", Game::INPUT_JOYSTICK1, "NONE");
down[0] = AddSwitchInput("JoyDown", "P1 Joystick Down", GAME_INPUT_JOYSTICK1, "NONE"); down[0] = AddSwitchInput("JoyDown", "P1 Joystick Down", Game::INPUT_JOYSTICK1, "NONE");
left[0] = AddSwitchInput("JoyLeft", "P1 Joystick Left", GAME_INPUT_JOYSTICK1, "NONE"); left[0] = AddSwitchInput("JoyLeft", "P1 Joystick Left", Game::INPUT_JOYSTICK1, "NONE");
right[0] = AddSwitchInput("JoyRight", "P1 Joystick Right", GAME_INPUT_JOYSTICK1, "NONE"); right[0] = AddSwitchInput("JoyRight", "P1 Joystick Right", Game::INPUT_JOYSTICK1, "NONE");
up[1] = AddSwitchInput("JoyUp2", "P2 Joystick Up", GAME_INPUT_JOYSTICK2, "NONE"); up[1] = AddSwitchInput("JoyUp2", "P2 Joystick Up", Game::INPUT_JOYSTICK2, "NONE");
down[1] = AddSwitchInput("JoyDown2", "P2 Joystick Down", GAME_INPUT_JOYSTICK2, "NONE"); down[1] = AddSwitchInput("JoyDown2", "P2 Joystick Down", Game::INPUT_JOYSTICK2, "NONE");
left[1] = AddSwitchInput("JoyLeft2", "P2 Joystick Left", GAME_INPUT_JOYSTICK2, "NONE"); left[1] = AddSwitchInput("JoyLeft2", "P2 Joystick Left", Game::INPUT_JOYSTICK2, "NONE");
right[1] = AddSwitchInput("JoyRight2", "P2 Joystick Right", GAME_INPUT_JOYSTICK2, "NONE"); right[1] = AddSwitchInput("JoyRight2", "P2 Joystick Right", Game::INPUT_JOYSTICK2, "NONE");
// Fighting Game Buttons // Fighting Game Buttons
punch[0] = AddSwitchInput("Punch", "P1 Punch", GAME_INPUT_FIGHTING, "NONE"); punch[0] = AddSwitchInput("Punch", "P1 Punch", Game::INPUT_FIGHTING, "NONE");
kick[0] = AddSwitchInput("Kick", "P1 Kick", GAME_INPUT_FIGHTING, "NONE"); kick[0] = AddSwitchInput("Kick", "P1 Kick", Game::INPUT_FIGHTING, "NONE");
guard[0] = AddSwitchInput("Guard", "P1 Guard", GAME_INPUT_FIGHTING, "NONE"); guard[0] = AddSwitchInput("Guard", "P1 Guard", Game::INPUT_FIGHTING, "NONE");
escape[0] = AddSwitchInput("Escape", "P1 Escape", GAME_INPUT_FIGHTING, "NONE"); escape[0] = AddSwitchInput("Escape", "P1 Escape", Game::INPUT_FIGHTING, "NONE");
punch[1] = AddSwitchInput("Punch2", "P2 Punch", GAME_INPUT_FIGHTING, "NONE"); punch[1] = AddSwitchInput("Punch2", "P2 Punch", Game::INPUT_FIGHTING, "NONE");
kick[1] = AddSwitchInput("Kick2", "P2 Kick", GAME_INPUT_FIGHTING, "NONE"); kick[1] = AddSwitchInput("Kick2", "P2 Kick", Game::INPUT_FIGHTING, "NONE");
guard[1] = AddSwitchInput("Guard2", "P2 Guard", GAME_INPUT_FIGHTING, "NONE"); guard[1] = AddSwitchInput("Guard2", "P2 Guard", Game::INPUT_FIGHTING, "NONE");
escape[1] = AddSwitchInput("Escape2", "P2 Escape", GAME_INPUT_FIGHTING, "NONE"); escape[1] = AddSwitchInput("Escape2", "P2 Escape", Game::INPUT_FIGHTING, "NONE");
// Spikeout Buttons // Spikeout Buttons
shift = AddSwitchInput("Shift", "Shift", GAME_INPUT_SPIKEOUT, "NONE"); shift = AddSwitchInput("Shift", "Shift", Game::INPUT_SPIKEOUT, "NONE");
beat = AddSwitchInput("Beat", "Beat", GAME_INPUT_SPIKEOUT, "NONE"); beat = AddSwitchInput("Beat", "Beat", Game::INPUT_SPIKEOUT, "NONE");
charge = AddSwitchInput("Charge", "Charge",GAME_INPUT_SPIKEOUT, "NONE"); charge = AddSwitchInput("Charge", "Charge",Game::INPUT_SPIKEOUT, "NONE");
jump = AddSwitchInput("Jump", "Jump", GAME_INPUT_SPIKEOUT, "NONE"); jump = AddSwitchInput("Jump", "Jump", Game::INPUT_SPIKEOUT, "NONE");
// Virtua Striker Buttons // Virtua Striker Buttons
shortPass[0] = AddSwitchInput("ShortPass", "P1 Short Pass", GAME_INPUT_SOCCER, "NONE"); shortPass[0] = AddSwitchInput("ShortPass", "P1 Short Pass", Game::INPUT_SOCCER, "NONE");
longPass[0] = AddSwitchInput("LongPass", "P1 Long Pass", GAME_INPUT_SOCCER, "NONE"); longPass[0] = AddSwitchInput("LongPass", "P1 Long Pass", Game::INPUT_SOCCER, "NONE");
shoot[0] = AddSwitchInput("Shoot", "P1 Shoot", GAME_INPUT_SOCCER, "NONE"); shoot[0] = AddSwitchInput("Shoot", "P1 Shoot", Game::INPUT_SOCCER, "NONE");
shortPass[1] = AddSwitchInput("ShortPass2", "P2 Short Pass", GAME_INPUT_SOCCER, "NONE"); shortPass[1] = AddSwitchInput("ShortPass2", "P2 Short Pass", Game::INPUT_SOCCER, "NONE");
longPass[1] = AddSwitchInput("LongPass2", "P2 Long Pass", GAME_INPUT_SOCCER, "NONE"); longPass[1] = AddSwitchInput("LongPass2", "P2 Long Pass", Game::INPUT_SOCCER, "NONE");
shoot[1] = AddSwitchInput("Shoot2", "P2 Shoot", GAME_INPUT_SOCCER, "NONE"); shoot[1] = AddSwitchInput("Shoot2", "P2 Shoot", Game::INPUT_SOCCER, "NONE");
// Racing Game Steering Controls // Racing Game Steering Controls
CAnalogInput *steeringLeft = AddAnalogInput("SteeringLeft", "Steer Left", GAME_INPUT_VEHICLE, "NONE"); CAnalogInput *steeringLeft = AddAnalogInput("SteeringLeft", "Steer Left", Game::INPUT_VEHICLE, "NONE");
CAnalogInput *steeringRight = AddAnalogInput("SteeringRight", "Steer Right", GAME_INPUT_VEHICLE, "NONE"); CAnalogInput *steeringRight = AddAnalogInput("SteeringRight", "Steer Right", Game::INPUT_VEHICLE, "NONE");
steering = AddAxisInput ("Steering", "Full Steering", GAME_INPUT_VEHICLE, "NONE", steeringLeft, steeringRight); steering = AddAxisInput ("Steering", "Full Steering", Game::INPUT_VEHICLE, "NONE", steeringLeft, steeringRight);
accelerator = AddAnalogInput("Accelerator", "Accelerator Pedal", GAME_INPUT_VEHICLE, "NONE"); accelerator = AddAnalogInput("Accelerator", "Accelerator Pedal", Game::INPUT_VEHICLE, "NONE");
brake = AddAnalogInput("Brake", "Brake Pedal/Front Brake", GAME_INPUT_VEHICLE, "NONE"); brake = AddAnalogInput("Brake", "Brake Pedal/Front Brake", Game::INPUT_VEHICLE, "NONE");
gearShiftUp = AddSwitchInput("GearShiftUp", "Shift Up", GAME_INPUT_VEHICLE, "NONE"); gearShiftUp = AddSwitchInput("GearShiftUp", "Shift Up", Game::INPUT_VEHICLE, "NONE");
gearShiftDown = AddSwitchInput("GearShiftDown", "Shift Down", GAME_INPUT_VEHICLE, "NONE"); gearShiftDown = AddSwitchInput("GearShiftDown", "Shift Down", Game::INPUT_VEHICLE, "NONE");
// Racing Game Gear Shift // Racing Game Gear Shift
CSwitchInput *shift1 = AddSwitchInput("GearShift1", "Shift 1", GAME_INPUT_SHIFT4, "NONE"); CSwitchInput *shift1 = AddSwitchInput("GearShift1", "Shift 1", Game::INPUT_SHIFT4, "NONE");
CSwitchInput *shift2 = AddSwitchInput("GearShift2", "Shift 2", GAME_INPUT_SHIFT4, "NONE"); CSwitchInput *shift2 = AddSwitchInput("GearShift2", "Shift 2", Game::INPUT_SHIFT4, "NONE");
CSwitchInput *shift3 = AddSwitchInput("GearShift3", "Shift 3", GAME_INPUT_SHIFT4, "NONE"); CSwitchInput *shift3 = AddSwitchInput("GearShift3", "Shift 3", Game::INPUT_SHIFT4, "NONE");
CSwitchInput *shift4 = AddSwitchInput("GearShift4", "Shift 4", GAME_INPUT_SHIFT4, "NONE"); CSwitchInput *shift4 = AddSwitchInput("GearShift4", "Shift 4", Game::INPUT_SHIFT4, "NONE");
CSwitchInput *shiftN = AddSwitchInput("GearShiftN", "Shift Neutral", GAME_INPUT_SHIFT4, "NONE"); CSwitchInput *shiftN = AddSwitchInput("GearShiftN", "Shift Neutral", Game::INPUT_SHIFT4, "NONE");
gearShift4 = AddGearShift4Input("GearShift", "Gear Shift", GAME_INPUT_SHIFT4, shift1, shift2, shift3, shift4, shiftN, gearShiftUp, gearShiftDown); gearShift4 = AddGearShift4Input("GearShift", "Gear Shift", Game::INPUT_SHIFT4, shift1, shift2, shift3, shift4, shiftN, gearShiftUp, gearShiftDown);
// Racing Game 4 VR View Buttons // Racing Game 4 VR View Buttons
vr[0] = AddSwitchInput("VR1", "VR1", GAME_INPUT_VR4, "NONE"); vr[0] = AddSwitchInput("VR1", "VR1", Game::INPUT_VR4, "NONE");
vr[1] = AddSwitchInput("VR2", "VR2", GAME_INPUT_VR4, "NONE"); vr[1] = AddSwitchInput("VR2", "VR2", Game::INPUT_VR4, "NONE");
vr[2] = AddSwitchInput("VR3", "VR3", GAME_INPUT_VR4, "NONE"); vr[2] = AddSwitchInput("VR3", "VR3", Game::INPUT_VR4, "NONE");
vr[3] = AddSwitchInput("VR4", "VR4", GAME_INPUT_VR4, "NONE"); vr[3] = AddSwitchInput("VR4", "VR4", Game::INPUT_VR4, "NONE");
// Racing Game Single View Change Button // Racing Game Single View Change Button
viewChange = AddSwitchInput("ViewChange", "View Change", GAME_INPUT_VIEWCHANGE, "NONE"); viewChange = AddSwitchInput("ViewChange", "View Change", Game::INPUT_VIEWCHANGE, "NONE");
// Racing Game Handbrake // Racing Game Handbrake
handBrake = AddSwitchInput("HandBrake", "Hand Brake", GAME_INPUT_HANDBRAKE, "NONE"); handBrake = AddSwitchInput("HandBrake", "Hand Brake", Game::INPUT_HANDBRAKE, "NONE");
// Harley Davidson Controls // Harley Davidson Controls
rearBrake = AddAnalogInput("RearBrake", "Rear Brake", GAME_INPUT_HARLEY, "NONE"); rearBrake = AddAnalogInput("RearBrake", "Rear Brake", Game::INPUT_HARLEY, "NONE");
musicSelect = AddSwitchInput("MusicSelect", "Music Selection", GAME_INPUT_HARLEY, "NONE"); musicSelect = AddSwitchInput("MusicSelect", "Music Selection", Game::INPUT_HARLEY, "NONE");
// Virtual On Controls // Virtual On Controls
twinJoyTurnLeft = AddSwitchInput("TwinJoyTurnLeft", "Macro Turn Left", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyTurnLeft = AddSwitchInput("TwinJoyTurnLeft", "Macro Turn Left", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyTurnRight = AddSwitchInput("TwinJoyTurnRight", "Macro Turn Right", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyTurnRight = AddSwitchInput("TwinJoyTurnRight", "Macro Turn Right", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyForward = AddSwitchInput("TwinJoyForward", "Macro Forward", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyForward = AddSwitchInput("TwinJoyForward", "Macro Forward", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyReverse = AddSwitchInput("TwinJoyReverse", "Macro Reverse", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyReverse = AddSwitchInput("TwinJoyReverse", "Macro Reverse", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyStrafeLeft = AddSwitchInput("TwinJoyStrafeLeft", "Macro Strafe Left", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyStrafeLeft = AddSwitchInput("TwinJoyStrafeLeft", "Macro Strafe Left", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyStrafeRight = AddSwitchInput("TwinJoyStrafeRight", "Macro Strafe Right", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyStrafeRight = AddSwitchInput("TwinJoyStrafeRight", "Macro Strafe Right", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyJump = AddSwitchInput("TwinJoyJump", "Macro Jump", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyJump = AddSwitchInput("TwinJoyJump", "Macro Jump", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyCrouch = AddSwitchInput("TwinJoyCrouch", "Macro Crouch", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyCrouch = AddSwitchInput("TwinJoyCrouch", "Macro Crouch", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyLeft1 = AddSwitchInput("TwinJoyLeft1", "Left Joystick Left", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyLeft1 = AddSwitchInput("TwinJoyLeft1", "Left Joystick Left", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyLeft2 = AddSwitchInput("TwinJoyLeft2", "Right Joystick Left", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyLeft2 = AddSwitchInput("TwinJoyLeft2", "Right Joystick Left", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyRight1 = AddSwitchInput("TwinJoyRight1", "Left Joystick Right", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyRight1 = AddSwitchInput("TwinJoyRight1", "Left Joystick Right", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyRight2 = AddSwitchInput("TwinJoyRight2", "Right Joystick Right", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyRight2 = AddSwitchInput("TwinJoyRight2", "Right Joystick Right", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyUp1 = AddSwitchInput("TwinJoyUp1", "Left Joystick Up", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyUp1 = AddSwitchInput("TwinJoyUp1", "Left Joystick Up", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyUp2 = AddSwitchInput("TwinJoyUp2", "Right Joystick Up", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyUp2 = AddSwitchInput("TwinJoyUp2", "Right Joystick Up", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyDown1 = AddSwitchInput("TwinJoyDown1", "Left Joystick Down", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyDown1 = AddSwitchInput("TwinJoyDown1", "Left Joystick Down", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyDown2 = AddSwitchInput("TwinJoyDown2", "Right Joystick Down", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyDown2 = AddSwitchInput("TwinJoyDown2", "Right Joystick Down", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyShot1 = AddSwitchInput("TwinJoyShot1", "Left Shot Trigger", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyShot1 = AddSwitchInput("TwinJoyShot1", "Left Shot Trigger", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyShot2 = AddSwitchInput("TwinJoyShot2", "Right Shot Trigger", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyShot2 = AddSwitchInput("TwinJoyShot2", "Right Shot Trigger", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyTurbo1 = AddSwitchInput("TwinJoyTurbo1", "Left Turbo", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyTurbo1 = AddSwitchInput("TwinJoyTurbo1", "Left Turbo", Game::INPUT_TWIN_JOYSTICKS, "NONE");
twinJoyTurbo2 = AddSwitchInput("TwinJoyTurbo2", "Right Turbo", GAME_INPUT_TWIN_JOYSTICKS, "NONE"); twinJoyTurbo2 = AddSwitchInput("TwinJoyTurbo2", "Right Turbo", Game::INPUT_TWIN_JOYSTICKS, "NONE");
// Analog Joystick // Analog Joystick
CAnalogInput *analogJoyLeft = AddAnalogInput("AnalogJoyLeft", "Analog Left", GAME_INPUT_ANALOG_JOYSTICK, "NONE"); CAnalogInput *analogJoyLeft = AddAnalogInput("AnalogJoyLeft", "Analog Left", Game::INPUT_ANALOG_JOYSTICK, "NONE");
CAnalogInput *analogJoyRight = AddAnalogInput("AnalogJoyRight", "Analog Right", GAME_INPUT_ANALOG_JOYSTICK, "NONE"); CAnalogInput *analogJoyRight = AddAnalogInput("AnalogJoyRight", "Analog Right", Game::INPUT_ANALOG_JOYSTICK, "NONE");
CAnalogInput *analogJoyUp = AddAnalogInput("AnalogJoyUp", "Analog Up", GAME_INPUT_ANALOG_JOYSTICK, "NONE"); CAnalogInput *analogJoyUp = AddAnalogInput("AnalogJoyUp", "Analog Up", Game::INPUT_ANALOG_JOYSTICK, "NONE");
CAnalogInput *analogJoyDown = AddAnalogInput("AnalogJoyDown", "Analog Down", GAME_INPUT_ANALOG_JOYSTICK, "NONE"); CAnalogInput *analogJoyDown = AddAnalogInput("AnalogJoyDown", "Analog Down", Game::INPUT_ANALOG_JOYSTICK, "NONE");
analogJoyX = AddAxisInput ("AnalogJoyX", "Analog X-Axis", GAME_INPUT_ANALOG_JOYSTICK, "NONE", analogJoyLeft, analogJoyRight); analogJoyX = AddAxisInput ("AnalogJoyX", "Analog X-Axis", Game::INPUT_ANALOG_JOYSTICK, "NONE", analogJoyLeft, analogJoyRight);
analogJoyY = AddAxisInput ("AnalogJoyY", "Analog Y-Axis", GAME_INPUT_ANALOG_JOYSTICK, "NONE", analogJoyUp, analogJoyDown); analogJoyY = AddAxisInput ("AnalogJoyY", "Analog Y-Axis", Game::INPUT_ANALOG_JOYSTICK, "NONE", analogJoyUp, analogJoyDown);
analogJoyTrigger1 = AddSwitchInput("AnalogJoyTrigger", "Trigger Button 1", GAME_INPUT_ANALOG_JOYSTICK, "NONE"); analogJoyTrigger1 = AddSwitchInput("AnalogJoyTrigger", "Trigger Button 1", Game::INPUT_ANALOG_JOYSTICK, "NONE");
analogJoyTrigger2 = AddSwitchInput("AnalogJoyTrigger2", "Trigger Button 2", GAME_INPUT_ANALOG_JOYSTICK, "NONE"); analogJoyTrigger2 = AddSwitchInput("AnalogJoyTrigger2", "Trigger Button 2", Game::INPUT_ANALOG_JOYSTICK, "NONE");
analogJoyEvent1 = AddSwitchInput("AnalogJoyEvent", "Event Button 1", GAME_INPUT_ANALOG_JOYSTICK, "NONE"); analogJoyEvent1 = AddSwitchInput("AnalogJoyEvent", "Event Button 1", Game::INPUT_ANALOG_JOYSTICK, "NONE");
analogJoyEvent2 = AddSwitchInput("AnalogJoyEvent2", "Event Button 2", GAME_INPUT_ANALOG_JOYSTICK, "NONE"); analogJoyEvent2 = AddSwitchInput("AnalogJoyEvent2", "Event Button 2", Game::INPUT_ANALOG_JOYSTICK, "NONE");
// Light guns // Light guns
CAnalogInput *gun1Left = AddAnalogInput("GunLeft", "P1 Gun Left", GAME_INPUT_GUN1, "NONE"); CAnalogInput *gun1Left = AddAnalogInput("GunLeft", "P1 Gun Left", Game::INPUT_GUN1, "NONE");
CAnalogInput *gun1Right = AddAnalogInput("GunRight", "P1 Gun Right", GAME_INPUT_GUN1, "NONE"); CAnalogInput *gun1Right = AddAnalogInput("GunRight", "P1 Gun Right", Game::INPUT_GUN1, "NONE");
CAnalogInput *gun1Up = AddAnalogInput("GunUp", "P1 Gun Up", GAME_INPUT_GUN1, "NONE"); CAnalogInput *gun1Up = AddAnalogInput("GunUp", "P1 Gun Up", Game::INPUT_GUN1, "NONE");
CAnalogInput *gun1Down = AddAnalogInput("GunDown", "P1 Gun Down", GAME_INPUT_GUN1, "NONE"); CAnalogInput *gun1Down = AddAnalogInput("GunDown", "P1 Gun Down", Game::INPUT_GUN1, "NONE");
gunX[0] = AddAxisInput("GunX", "P1 Gun X-Axis", GAME_INPUT_GUN1, "NONE", gun1Left, gun1Right, 150, 400, 651); // normalize to [150,651] gunX[0] = AddAxisInput("GunX", "P1 Gun X-Axis", Game::INPUT_GUN1, "NONE", gun1Left, gun1Right, 150, 400, 651); // normalize to [150,651]
gunY[0] = AddAxisInput("GunY", "P1 Gun Y-Axis", GAME_INPUT_GUN1, "NONE", gun1Up, gun1Down, 80, 272, 465); // normalize to [80,465] gunY[0] = AddAxisInput("GunY", "P1 Gun Y-Axis", Game::INPUT_GUN1, "NONE", gun1Up, gun1Down, 80, 272, 465); // normalize to [80,465]
CSwitchInput *gun1Trigger = AddSwitchInput("Trigger", "P1 Trigger", GAME_INPUT_GUN1, "NONE"); CSwitchInput *gun1Trigger = AddSwitchInput("Trigger", "P1 Trigger", Game::INPUT_GUN1, "NONE");
CSwitchInput *gun1Offscreen = AddSwitchInput("Offscreen", "P1 Point Off-screen", GAME_INPUT_GUN1, "NONE"); CSwitchInput *gun1Offscreen = AddSwitchInput("Offscreen", "P1 Point Off-screen", Game::INPUT_GUN1, "NONE");
trigger[0] = AddTriggerInput("AutoTrigger", "P1 Auto Trigger", GAME_INPUT_GUN1, gun1Trigger, gun1Offscreen); trigger[0] = AddTriggerInput("AutoTrigger", "P1 Auto Trigger", Game::INPUT_GUN1, gun1Trigger, gun1Offscreen);
CAnalogInput *gun2Left = AddAnalogInput("GunLeft2", "P2 Gun Left", GAME_INPUT_GUN2, "NONE"); CAnalogInput *gun2Left = AddAnalogInput("GunLeft2", "P2 Gun Left", Game::INPUT_GUN2, "NONE");
CAnalogInput *gun2Right = AddAnalogInput("GunRight2", "P2 Gun Right", GAME_INPUT_GUN2, "NONE"); CAnalogInput *gun2Right = AddAnalogInput("GunRight2", "P2 Gun Right", Game::INPUT_GUN2, "NONE");
CAnalogInput *gun2Up = AddAnalogInput("GunUp2", "P2 Gun Up", GAME_INPUT_GUN2, "NONE"); CAnalogInput *gun2Up = AddAnalogInput("GunUp2", "P2 Gun Up", Game::INPUT_GUN2, "NONE");
CAnalogInput *gun2Down = AddAnalogInput("GunDown2", "P2 Gun Down", GAME_INPUT_GUN2, "NONE"); CAnalogInput *gun2Down = AddAnalogInput("GunDown2", "P2 Gun Down", Game::INPUT_GUN2, "NONE");
gunX[1] = AddAxisInput("GunX2", "P2 Gun X-Axis", GAME_INPUT_GUN2, "NONE", gun2Left, gun2Right, 150, 400, 651); // normalize to [150,651] gunX[1] = AddAxisInput("GunX2", "P2 Gun X-Axis", Game::INPUT_GUN2, "NONE", gun2Left, gun2Right, 150, 400, 651); // normalize to [150,651]
gunY[1] = AddAxisInput("GunY2", "P2 Gun Y-Axis", GAME_INPUT_GUN2, "NONE", gun2Up, gun2Down, 80, 272, 465); // normalize to [80,465] gunY[1] = AddAxisInput("GunY2", "P2 Gun Y-Axis", Game::INPUT_GUN2, "NONE", gun2Up, gun2Down, 80, 272, 465); // normalize to [80,465]
CSwitchInput *gun2Trigger = AddSwitchInput("Trigger2", "P2 Trigger", GAME_INPUT_GUN2, "NONE"); CSwitchInput *gun2Trigger = AddSwitchInput("Trigger2", "P2 Trigger", Game::INPUT_GUN2, "NONE");
CSwitchInput *gun2Offscreen = AddSwitchInput("Offscreen2", "P2 Point Off-screen", GAME_INPUT_GUN2, "NONE"); CSwitchInput *gun2Offscreen = AddSwitchInput("Offscreen2", "P2 Point Off-screen", Game::INPUT_GUN2, "NONE");
trigger[1] = AddTriggerInput("AutoTrigger2", "P2 Auto Trigger", GAME_INPUT_GUN2, gun2Trigger, gun2Offscreen); trigger[1] = AddTriggerInput("AutoTrigger2", "P2 Auto Trigger", Game::INPUT_GUN2, gun2Trigger, gun2Offscreen);
// Analog guns // Analog guns
CAnalogInput *analogGun1Left = AddAnalogInput("AnalogGunLeft", "P1 Analog Gun Left", GAME_INPUT_ANALOG_GUN1, "NONE"); CAnalogInput *analogGun1Left = AddAnalogInput("AnalogGunLeft", "P1 Analog Gun Left", Game::INPUT_ANALOG_GUN1, "NONE");
CAnalogInput *analogGun1Right = AddAnalogInput("AnalogGunRight", "P1 Analog Gun Right", GAME_INPUT_ANALOG_GUN1, "NONE"); CAnalogInput *analogGun1Right = AddAnalogInput("AnalogGunRight", "P1 Analog Gun Right", Game::INPUT_ANALOG_GUN1, "NONE");
CAnalogInput *analogGun1Up = AddAnalogInput("AnalogGunUp", "P1 Analog Gun Up", GAME_INPUT_ANALOG_GUN1, "NONE"); CAnalogInput *analogGun1Up = AddAnalogInput("AnalogGunUp", "P1 Analog Gun Up", Game::INPUT_ANALOG_GUN1, "NONE");
CAnalogInput *analogGun1Down = AddAnalogInput("AnalogGunDown", "P1 Analog Gun Down", GAME_INPUT_ANALOG_GUN1, "NONE"); CAnalogInput *analogGun1Down = AddAnalogInput("AnalogGunDown", "P1 Analog Gun Down", Game::INPUT_ANALOG_GUN1, "NONE");
analogGunX[0] = AddAxisInput("AnalogGunX", "P1 Analog Gun X-Axis", GAME_INPUT_ANALOG_GUN1, "NONE", analogGun1Left, analogGun1Right, 0, 0x80, 0xFF); analogGunX[0] = AddAxisInput("AnalogGunX", "P1 Analog Gun X-Axis", Game::INPUT_ANALOG_GUN1, "NONE", analogGun1Left, analogGun1Right, 0, 0x80, 0xFF);
analogGunY[0] = AddAxisInput("AnalogGunY", "P1 Analog Gun Y-Axis", GAME_INPUT_ANALOG_GUN1, "NONE", analogGun1Up, analogGun1Down, 0xFF, 0x80, 0); analogGunY[0] = AddAxisInput("AnalogGunY", "P1 Analog Gun Y-Axis", Game::INPUT_ANALOG_GUN1, "NONE", analogGun1Up, analogGun1Down, 0xFF, 0x80, 0);
analogTriggerLeft[0] = AddSwitchInput("AnalogTriggerLeft", "P1 Analog Gun Left Trigger", GAME_INPUT_ANALOG_GUN1, "NONE"); analogTriggerLeft[0] = AddSwitchInput("AnalogTriggerLeft", "P1 Analog Gun Left Trigger", Game::INPUT_ANALOG_GUN1, "NONE");
analogTriggerRight[0] = AddSwitchInput("AnalogTriggerRight", "P1 Analog Gun Right Trigger", GAME_INPUT_ANALOG_GUN1, "NONE"); analogTriggerRight[0] = AddSwitchInput("AnalogTriggerRight", "P1 Analog Gun Right Trigger", Game::INPUT_ANALOG_GUN1, "NONE");
CAnalogInput *analogGun2Left = AddAnalogInput("AnalogGunLeft2", "P2 Analog Gun Left", GAME_INPUT_ANALOG_GUN2, "NONE"); CAnalogInput *analogGun2Left = AddAnalogInput("AnalogGunLeft2", "P2 Analog Gun Left", Game::INPUT_ANALOG_GUN2, "NONE");
CAnalogInput *analogGun2Right = AddAnalogInput("AnalogGunRight2", "P2 Analog Gun Right", GAME_INPUT_ANALOG_GUN2, "NONE"); CAnalogInput *analogGun2Right = AddAnalogInput("AnalogGunRight2", "P2 Analog Gun Right", Game::INPUT_ANALOG_GUN2, "NONE");
CAnalogInput *analogGun2Up = AddAnalogInput("AnalogGunUp2", "P2 Analog Gun Up", GAME_INPUT_ANALOG_GUN2, "NONE"); CAnalogInput *analogGun2Up = AddAnalogInput("AnalogGunUp2", "P2 Analog Gun Up", Game::INPUT_ANALOG_GUN2, "NONE");
CAnalogInput *analogGun2Down = AddAnalogInput("AnalogGunDown2", "P2 Analog Gun Down", GAME_INPUT_ANALOG_GUN2, "NONE"); CAnalogInput *analogGun2Down = AddAnalogInput("AnalogGunDown2", "P2 Analog Gun Down", Game::INPUT_ANALOG_GUN2, "NONE");
analogGunX[1] = AddAxisInput("AnalogGunX2", "P2 Analog Gun X-Axis", GAME_INPUT_ANALOG_GUN2, "NONE", analogGun2Left, analogGun2Right, 0, 0x80, 0xFF); analogGunX[1] = AddAxisInput("AnalogGunX2", "P2 Analog Gun X-Axis", Game::INPUT_ANALOG_GUN2, "NONE", analogGun2Left, analogGun2Right, 0, 0x80, 0xFF);
analogGunY[1] = AddAxisInput("AnalogGunY2", "P2 Analog Gun Y-Axis", GAME_INPUT_ANALOG_GUN2, "NONE", analogGun2Up, analogGun2Down, 0xFF, 0x80, 0); analogGunY[1] = AddAxisInput("AnalogGunY2", "P2 Analog Gun Y-Axis", Game::INPUT_ANALOG_GUN2, "NONE", analogGun2Up, analogGun2Down, 0xFF, 0x80, 0);
analogTriggerLeft[1] = AddSwitchInput("AnalogTriggerLeft2", "P2 Analog Gun Left Trigger", GAME_INPUT_ANALOG_GUN2, "NONE"); analogTriggerLeft[1] = AddSwitchInput("AnalogTriggerLeft2", "P2 Analog Gun Left Trigger", Game::INPUT_ANALOG_GUN2, "NONE");
analogTriggerRight[1] = AddSwitchInput("AnalogTriggerRight2", "P2 Analog Gun Right Trigger", GAME_INPUT_ANALOG_GUN2, "NONE"); analogTriggerRight[1] = AddSwitchInput("AnalogTriggerRight2", "P2 Analog Gun Right Trigger", Game::INPUT_ANALOG_GUN2, "NONE");
// Ski controls // Ski controls
CAnalogInput *skiLeft = AddAnalogInput("SkiLeft", "Ski Champ Left", GAME_INPUT_SKI, "NONE"); CAnalogInput *skiLeft = AddAnalogInput("SkiLeft", "Ski Champ Left", Game::INPUT_SKI, "NONE");
CAnalogInput *skiRight = AddAnalogInput("SkiRight", "Ski Champ Right", GAME_INPUT_SKI, "NONE"); CAnalogInput *skiRight = AddAnalogInput("SkiRight", "Ski Champ Right", Game::INPUT_SKI, "NONE");
CAnalogInput *skiUp = AddAnalogInput("SkiUp", "Ski Champ Up", GAME_INPUT_SKI, "NONE"); CAnalogInput *skiUp = AddAnalogInput("SkiUp", "Ski Champ Up", Game::INPUT_SKI, "NONE");
CAnalogInput *skiDown = AddAnalogInput("SkiDown", "Ski Champ Down", GAME_INPUT_SKI, "NONE"); CAnalogInput *skiDown = AddAnalogInput("SkiDown", "Ski Champ Down", Game::INPUT_SKI, "NONE");
skiX = AddAxisInput ("SkiX", "Ski Champ X-Axis", GAME_INPUT_SKI, "NONE", skiLeft, skiRight, 0xFF, 0x80, 0); skiX = AddAxisInput ("SkiX", "Ski Champ X-Axis", Game::INPUT_SKI, "NONE", skiLeft, skiRight, 0xFF, 0x80, 0);
skiY = AddAxisInput ("SkiY", "Ski Champ Y-Axis", GAME_INPUT_SKI, "NONE", skiUp, skiDown); skiY = AddAxisInput ("SkiY", "Ski Champ Y-Axis", Game::INPUT_SKI, "NONE", skiUp, skiDown);
skiPollLeft = AddSwitchInput("SkiPollLeft", "Ski Champ Poll Left", GAME_INPUT_SKI, "NONE"); skiPollLeft = AddSwitchInput("SkiPollLeft", "Ski Champ Poll Left", Game::INPUT_SKI, "NONE");
skiPollRight = AddSwitchInput("SkiPollRight", "Ski Champ Poll Right", GAME_INPUT_SKI, "NONE"); skiPollRight = AddSwitchInput("SkiPollRight", "Ski Champ Poll Right", Game::INPUT_SKI, "NONE");
skiSelect1 = AddSwitchInput("SkiSelect1", "Ski Champ Select 1", GAME_INPUT_SKI, "NONE"); skiSelect1 = AddSwitchInput("SkiSelect1", "Ski Champ Select 1", Game::INPUT_SKI, "NONE");
skiSelect2 = AddSwitchInput("SkiSelect2", "Ski Champ Select 2", GAME_INPUT_SKI, "NONE"); skiSelect2 = AddSwitchInput("SkiSelect2", "Ski Champ Select 2", Game::INPUT_SKI, "NONE");
skiSelect3 = AddSwitchInput("SkiSelect3", "Ski Champ Select 3", GAME_INPUT_SKI, "NONE"); skiSelect3 = AddSwitchInput("SkiSelect3", "Ski Champ Select 3", Game::INPUT_SKI, "NONE");
// Magical truck controls // Magical truck controls
CAnalogInput *magicalLeverUp1 = AddAnalogInput("MagicalLeverUp1", "P1 Magical Lever Up", GAME_INPUT_MAGTRUCK, "NONE"); CAnalogInput *magicalLeverUp1 = AddAnalogInput("MagicalLeverUp1", "P1 Magical Lever Up", Game::INPUT_MAGTRUCK, "NONE");
CAnalogInput *magicalLeverDown1 = AddAnalogInput("MagicalLeverDown1", "P1 Magical Lever Down", GAME_INPUT_MAGTRUCK, "NONE"); CAnalogInput *magicalLeverDown1 = AddAnalogInput("MagicalLeverDown1", "P1 Magical Lever Down", Game::INPUT_MAGTRUCK, "NONE");
CAnalogInput *magicalLeverUp2 = AddAnalogInput("MagicalLeverUp2", "P2 Magical Lever Up", GAME_INPUT_MAGTRUCK, "NONE"); CAnalogInput *magicalLeverUp2 = AddAnalogInput("MagicalLeverUp2", "P2 Magical Lever Up", Game::INPUT_MAGTRUCK, "NONE");
CAnalogInput *magicalLeverDown2 = AddAnalogInput("MagicalLeverDown2", "P2 Magical Lever Down", GAME_INPUT_MAGTRUCK, "NONE"); CAnalogInput *magicalLeverDown2 = AddAnalogInput("MagicalLeverDown2", "P2 Magical Lever Down", Game::INPUT_MAGTRUCK, "NONE");
magicalLever1 = AddAxisInput( "MagicalLever1", "P1 Magical Lever", GAME_INPUT_MAGTRUCK, "NONE", magicalLeverUp1, magicalLeverDown1, 0xFF, 0x80, 0); magicalLever1 = AddAxisInput( "MagicalLever1", "P1 Magical Lever", Game::INPUT_MAGTRUCK, "NONE", magicalLeverUp1, magicalLeverDown1, 0xFF, 0x80, 0);
magicalLever2 = AddAxisInput( "MagicalLever2", "P2 Magical Lever", GAME_INPUT_MAGTRUCK, "NONE", magicalLeverUp2, magicalLeverDown2, 0xFF, 0x80, 0); magicalLever2 = AddAxisInput( "MagicalLever2", "P2 Magical Lever", Game::INPUT_MAGTRUCK, "NONE", magicalLeverUp2, magicalLeverDown2, 0xFF, 0x80, 0);
magicalPedal1 = AddSwitchInput( "MagicalPedal1", "P1 Magical Pedal", GAME_INPUT_MAGTRUCK, "NONE"); magicalPedal1 = AddSwitchInput( "MagicalPedal1", "P1 Magical Pedal", Game::INPUT_MAGTRUCK, "NONE");
magicalPedal2 = AddSwitchInput( "MagicalPedal2", "P2 Magical Pedal", GAME_INPUT_MAGTRUCK, "NONE"); magicalPedal2 = AddSwitchInput( "MagicalPedal2", "P2 Magical Pedal", Game::INPUT_MAGTRUCK, "NONE");
// Sega Bass Fishing controls // Sega Bass Fishing controls
CAnalogInput *fishingRodLeft = AddAnalogInput("FishingRodLeft", "Rod Left", GAME_INPUT_FISHING, "NONE"); CAnalogInput *fishingRodLeft = AddAnalogInput("FishingRodLeft", "Rod Left", Game::INPUT_FISHING, "NONE");
CAnalogInput *fishingRodRight = AddAnalogInput("FishingRodRight", "Rod Right", GAME_INPUT_FISHING, "NONE"); CAnalogInput *fishingRodRight = AddAnalogInput("FishingRodRight", "Rod Right", Game::INPUT_FISHING, "NONE");
CAnalogInput *fishingRodUp = AddAnalogInput("FishingRodUp", "Rod Up", GAME_INPUT_FISHING, "NONE"); CAnalogInput *fishingRodUp = AddAnalogInput("FishingRodUp", "Rod Up", Game::INPUT_FISHING, "NONE");
CAnalogInput *fishingRodDown = AddAnalogInput("FishingRodDown", "Rod Down", GAME_INPUT_FISHING, "NONE"); CAnalogInput *fishingRodDown = AddAnalogInput("FishingRodDown", "Rod Down", Game::INPUT_FISHING, "NONE");
CAnalogInput *fishingReelFaster = AddAnalogInput("FishingReelFaster", "Reel Faster", GAME_INPUT_FISHING, "NONE"); CAnalogInput *fishingReelFaster = AddAnalogInput("FishingReelFaster", "Reel Faster", Game::INPUT_FISHING, "NONE");
CAnalogInput *fishingReelSlower = AddAnalogInput("FishingReelSlower", "Reel Slower", GAME_INPUT_FISHING, "NONE"); CAnalogInput *fishingReelSlower = AddAnalogInput("FishingReelSlower", "Reel Slower", Game::INPUT_FISHING, "NONE");
CAnalogInput *fishingStickLeft = AddAnalogInput("FishingStickLeft", "Stick Left", GAME_INPUT_FISHING, "NONE"); CAnalogInput *fishingStickLeft = AddAnalogInput("FishingStickLeft", "Stick Left", Game::INPUT_FISHING, "NONE");
CAnalogInput *fishingStickRight = AddAnalogInput("FishingStickRight", "Stick Right", GAME_INPUT_FISHING, "NONE"); CAnalogInput *fishingStickRight = AddAnalogInput("FishingStickRight", "Stick Right", Game::INPUT_FISHING, "NONE");
CAnalogInput *fishingStickUp = AddAnalogInput("FishingStickUp", "Stick Up", GAME_INPUT_FISHING, "NONE"); CAnalogInput *fishingStickUp = AddAnalogInput("FishingStickUp", "Stick Up", Game::INPUT_FISHING, "NONE");
CAnalogInput *fishingStickDown = AddAnalogInput("FishingStickDown", "Stick Down", GAME_INPUT_FISHING, "NONE"); CAnalogInput *fishingStickDown = AddAnalogInput("FishingStickDown", "Stick Down", Game::INPUT_FISHING, "NONE");
fishingRodX = AddAxisInput( "FishingRodX", "Rod X-Axis", GAME_INPUT_FISHING, "NONE", fishingRodLeft, fishingRodRight, 0, 0x80, 0xFF); fishingRodX = AddAxisInput( "FishingRodX", "Rod X-Axis", Game::INPUT_FISHING, "NONE", fishingRodLeft, fishingRodRight, 0, 0x80, 0xFF);
fishingRodY = AddAxisInput( "FishingRodY", "Rod Y-Axis", GAME_INPUT_FISHING, "NONE", fishingRodUp, fishingRodDown, 0xFF, 0x80, 0); fishingRodY = AddAxisInput( "FishingRodY", "Rod Y-Axis", Game::INPUT_FISHING, "NONE", fishingRodUp, fishingRodDown, 0xFF, 0x80, 0);
fishingReel = AddAxisInput( "FishingReel", "Reel Speed", GAME_INPUT_FISHING, "NONE", fishingReelSlower, fishingReelFaster, 0, 0x80, 0xFF); fishingReel = AddAxisInput( "FishingReel", "Reel Speed", Game::INPUT_FISHING, "NONE", fishingReelSlower, fishingReelFaster, 0, 0x80, 0xFF);
fishingStickX = AddAxisInput( "FishingStickX", "Stick X-Axis", GAME_INPUT_FISHING, "NONE", fishingStickLeft, fishingStickRight, 0, 0x80, 0xFF); fishingStickX = AddAxisInput( "FishingStickX", "Stick X-Axis", Game::INPUT_FISHING, "NONE", fishingStickLeft, fishingStickRight, 0, 0x80, 0xFF);
fishingStickY = AddAxisInput( "FishingStickY", "Stick Y-Axis", GAME_INPUT_FISHING, "NONE", fishingStickUp, fishingStickDown, 0xFF, 0x80, 0); fishingStickY = AddAxisInput( "FishingStickY", "Stick Y-Axis", Game::INPUT_FISHING, "NONE", fishingStickUp, fishingStickDown, 0xFF, 0x80, 0);
fishingCast = AddSwitchInput( "FishingCast", "Cast", GAME_INPUT_FISHING, "NONE"); fishingCast = AddSwitchInput( "FishingCast", "Cast", Game::INPUT_FISHING, "NONE");
fishingSelect = AddSwitchInput( "FishingSelect", "Select", GAME_INPUT_FISHING, "NONE"); fishingSelect = AddSwitchInput( "FishingSelect", "Select", Game::INPUT_FISHING, "NONE");
} }
CInputs::~CInputs() CInputs::~CInputs()
@ -399,9 +401,26 @@ bool CInputs::Initialize()
// Initialize all the inputs // Initialize all the inputs
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++) for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
(*it)->Initialize(m_system); (*it)->Initialize(m_system);
return true; return true;
} }
void CInputs::LoadFromConfig(const Util::Config::Node &config)
{
m_system->LoadFromConfig(config);
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
(*it)->LoadFromConfig(config);
}
void CInputs::StoreToConfig(Util::Config::Node *config)
{
m_system->StoreToConfig(config);
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
(*it)->StoreToConfig(config);
}
void CInputs::ReadFromINIFile(CINIFile *ini, const char *section) void CInputs::ReadFromINIFile(CINIFile *ini, const char *section)
{ {
m_system->ReadFromINIFile(ini, section); m_system->ReadFromINIFile(ini, section);
@ -418,21 +437,21 @@ void CInputs::WriteToINIFile(CINIFile *ini, const char *section)
(*it)->WriteToINIFile(ini, section); (*it)->WriteToINIFile(ini, section);
} }
bool CInputs::ConfigureInputs(const GameInfo *game) bool CInputs::ConfigureInputs(const Game *game)
{ {
m_system->UngrabMouse(); m_system->UngrabMouse();
// Print header and help message // Print header and help message
int gameFlags; uint32_t gameFlags;
if (game != NULL) if (game)
{ {
PrintHeader("Configure Inputs for %s", game->title); PrintHeader("Configure Inputs for %s", game->title.c_str());
gameFlags = game->inputFlags; gameFlags = game->inputs;
} }
else else
{ {
PrintHeader("Configure Inputs"); PrintHeader("Configure Inputs");
gameFlags = GAME_INPUT_ALL; gameFlags = Game::INPUT_ALL;
} }
PrintConfigureInputsHelp(); PrintConfigureInputsHelp();
@ -599,7 +618,7 @@ Finish:
return !cancelled; return !cancelled;
} }
bool CInputs::ConfigureInputs(const GameInfo *game, unsigned dispX, unsigned dispY, unsigned dispW, unsigned dispH) bool CInputs::ConfigureInputs(const Game *game, unsigned dispX, unsigned dispY, unsigned dispW, unsigned dispH)
{ {
// Let the input system know the display geometry // Let the input system know the display geometry
m_system->SetDisplayGeom(dispX, dispY, dispW, dispH); m_system->SetDisplayGeom(dispX, dispY, dispW, dispH);
@ -697,19 +716,19 @@ void CInputs::CalibrateJoystick(int joyNum)
} }
} }
void CInputs::PrintInputs(const GameInfo *game) void CInputs::PrintInputs(const Game *game)
{ {
// Print header // Print header
int gameFlags; int gameFlags;
if (game != NULL) if (game != NULL)
{ {
PrintHeader("Input Assignments for %s", game->title); PrintHeader("Input Assignments for %s", game->title.c_str());
gameFlags = game->inputFlags; gameFlags = game->inputs;
} }
else else
{ {
PrintHeader("Input Assignments"); PrintHeader("Input Assignments");
gameFlags = GAME_INPUT_ALL; gameFlags = Game::INPUT_ALL;
} }
const char *groupLabel = NULL; const char *groupLabel = NULL;
@ -731,7 +750,7 @@ void CInputs::PrintInputs(const GameInfo *game)
puts(""); puts("");
} }
bool CInputs::Poll(const GameInfo *game, unsigned dispX, unsigned dispY, unsigned dispW, unsigned dispH) bool CInputs::Poll(const Game *game, unsigned dispX, unsigned dispY, unsigned dispW, unsigned dispH)
{ {
// Update the input system with the current display geometry // Update the input system with the current display geometry
m_system->SetDisplayGeom(dispX, dispY, dispW, dispH); m_system->SetDisplayGeom(dispX, dispY, dispW, dispH);
@ -741,7 +760,7 @@ bool CInputs::Poll(const GameInfo *game, unsigned dispX, unsigned dispY, unsigne
return false; return false;
// Poll all UI inputs and all the inputs used by the current game, or all inputs if game is NULL // Poll all UI inputs and all the inputs used by the current game, or all inputs if game is NULL
int gameFlags = (game != NULL ? game->inputFlags : GAME_INPUT_ALL); uint32_t gameFlags = game ? game->inputs : Game::INPUT_ALL;
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++) for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
{ {
if ((*it)->IsUIInput() || ((*it)->gameFlags & gameFlags)) if ((*it)->IsUIInput() || ((*it)->gameFlags & gameFlags))
@ -750,19 +769,19 @@ bool CInputs::Poll(const GameInfo *game, unsigned dispX, unsigned dispY, unsigne
return true; return true;
} }
void CInputs::DumpState(const GameInfo *game) void CInputs::DumpState(const Game *game)
{ {
// Print header // Print header
int gameFlags; int gameFlags;
if (game != NULL) if (game != NULL)
{ {
PrintHeader("Input States for %s", game->title); PrintHeader("Input States for %s", game->title.c_str());
gameFlags = game->inputFlags; gameFlags = game->inputs;
} }
else else
{ {
PrintHeader("Input States"); PrintHeader("Input States");
gameFlags = GAME_INPUT_ALL; gameFlags = Game::INPUT_ALL;
} }
// Loop through the inputs used by the current game, or all inputs if game is NULL, and dump their values to stdout // Loop through the inputs used by the current game, or all inputs if game is NULL, and dump their values to stdout

View file

@ -29,6 +29,7 @@
#define INCLUDED_INPUTS_H #define INCLUDED_INPUTS_H
#include "Types.h" #include "Types.h"
#include "Util/NewConfig.h"
#include <vector> #include <vector>
using namespace std; using namespace std;
@ -41,7 +42,7 @@ class CSwitchInput;
class CGearShift4Input; class CGearShift4Input;
class CTriggerInput; class CTriggerInput;
class CINIFile; class CINIFile;
struct GameInfo; struct Game;
/* /*
* Represents the collection of Model3 inputs. * Represents the collection of Model3 inputs.
@ -266,27 +267,29 @@ public:
bool Initialize(); bool Initialize();
/* /*
* Reads the input mapping assignments from the given INI file. * Loads the input mapping assignments from the given config object.
*/ */
void LoadFromConfig(const Util::Config::Node &config);
void ReadFromINIFile(CINIFile *ini, const char *section); void ReadFromINIFile(CINIFile *ini, const char *section);
/* /*
* Writes the current input mapping assignments to the given INI file. * Stores the current input mapping assignments to the given config object.
*/ */
void StoreToConfig(Util::Config::Node *config);
void WriteToINIFile(CINIFile *ini, const char *section); void WriteToINIFile(CINIFile *ini, const char *section);
/* /*
* Configures the current input mapping assignments for the given game, or all inputs if game is NULL, by asking the user for input. * Configures the current input mapping assignments for the given game, or all inputs if game is NULL, by asking the user for input.
* Returns true if the inputs were configured okay or false if the user exited without requesting to save changes. * Returns true if the inputs were configured okay or false if the user exited without requesting to save changes.
*/ */
bool ConfigureInputs(const GameInfo *game); bool ConfigureInputs(const Game *game);
/* /*
* Configures the current input mapping assignments for the given game, or all inputs if game is NULL, by asking the user for input. * Configures the current input mapping assignments for the given game, or all inputs if game is NULL, by asking the user for input.
* Takes display geometry if this has not been set previously by a call to Poll(). * Takes display geometry if this has not been set previously by a call to Poll().
* Returns true if the inputs were configured okay or false if the user exited without requesting to save changes. * Returns true if the inputs were configured okay or false if the user exited without requesting to save changes.
*/ */
bool ConfigureInputs(const GameInfo *game, unsigned dispX, unsigned dispY, unsigned dispW, unsigned dispH); bool ConfigureInputs(const Game *game, unsigned dispX, unsigned dispY, unsigned dispW, unsigned dispH);
void CalibrateJoysticks(); void CalibrateJoysticks();
@ -295,18 +298,18 @@ public:
/* /*
* Prints to stdout the current input mapping assignments for the given game, or all inputs if game is NULL. * Prints to stdout the current input mapping assignments for the given game, or all inputs if game is NULL.
*/ */
void PrintInputs(const GameInfo *game); void PrintInputs(const Game *game);
/* /*
* Polls (updates) the inputs for the given game, or all inputs if game is NULL, updating their values from their respective input sources. * Polls (updates) the inputs for the given game, or all inputs if game is NULL, updating their values from their respective input sources.
* First the input system is polled (CInputSystem.Poll()) and then each input is polled (CInput.Poll()). * First the input system is polled (CInputSystem.Poll()) and then each input is polled (CInput.Poll()).
*/ */
bool Poll(const GameInfo *game, unsigned dispX, unsigned dispY, unsigned dispW, unsigned dispH); bool Poll(const Game *game, unsigned dispX, unsigned dispY, unsigned dispW, unsigned dispH);
/* /*
* Prints the current values of the inputs for the given game, or all inputs if game is NULL, to stdout for debugging purposes. * Prints the current values of the inputs for the given game, or all inputs if game is NULL, to stdout for debugging purposes.
*/ */
void DumpState(const GameInfo *game); void DumpState(const Game *game);
}; };
#endif // INCLUDED_INPUTS_H #endif // INCLUDED_INPUTS_H

View file

@ -144,8 +144,8 @@ int CDSBResampler::UpSampleAndMix(INT16 *outL, INT16 *outR, INT16 *inL, INT16 *i
INT32 v[2], musicVol, soundVol; INT32 v[2], musicVol, soundVol;
// Obtain program volume settings and convert to 24.8 fixed point (0-200 -> 0x00-0x200) // Obtain program volume settings and convert to 24.8 fixed point (0-200 -> 0x00-0x200)
musicVol = g_Config.GetMusicVolume(); musicVol = m_config["MusicVolume"].ValueAs<int>();
soundVol = g_Config.GetSoundVolume(); soundVol = m_config["SoundVolume"].ValueAs<int>();
musicVol = (INT32) ((float) 0x100 * (float) musicVol / 100.0f); musicVol = (INT32) ((float) 0x100 * (float) musicVol / 100.0f);
soundVol = (INT32) ((float) 0x100 * (float) soundVol / 100.0f); soundVol = (INT32) ((float) 0x100 * (float) soundVol / 100.0f);
@ -426,7 +426,7 @@ void CDSB1::RunFrame(INT16 *audioL, INT16 *audioR)
int cycles; int cycles;
UINT8 v; UINT8 v;
if (!g_Config.emulateDSB) if (!m_config["EmulateDSB"].ValueAs<bool>())
{ {
// DSB code applies SCSP volume, too, so we must still mix // DSB code applies SCSP volume, too, so we must still mix
memset(mpegL, 0, (32000/60+2)*sizeof(INT16)); memset(mpegL, 0, (32000/60+2)*sizeof(INT16));
@ -603,7 +603,9 @@ CZ80 *CDSB1::GetZ80(void)
return &Z80; return &Z80;
} }
CDSB1::CDSB1(void) CDSB1::CDSB1(const Util::Config::Node &config)
: m_config(config),
Resampler(config)
{ {
progROM = NULL; progROM = NULL;
mpegROM = NULL; mpegROM = NULL;
@ -981,7 +983,7 @@ void CDSB2::SendCommand(UINT8 data)
void CDSB2::RunFrame(INT16 *audioL, INT16 *audioR) void CDSB2::RunFrame(INT16 *audioL, INT16 *audioR)
{ {
if (!g_Config.emulateDSB) if (!m_config["EmulateDSB"].ValueAs<bool>())
{ {
// DSB code applies SCSP volume, too, so we must still mix // DSB code applies SCSP volume, too, so we must still mix
memset(mpegL, 0, (32000/60+2)*sizeof(INT16)); memset(mpegL, 0, (32000/60+2)*sizeof(INT16));
@ -1184,7 +1186,9 @@ M68KCtx *CDSB2::GetM68K(void)
return &M68K; return &M68K;
} }
CDSB2::CDSB2(void) CDSB2::CDSB2(const Util::Config::Node &config)
: m_config(config),
Resampler(config)
{ {
progROM = NULL; progROM = NULL;
mpegROM = NULL; mpegROM = NULL;

View file

@ -33,83 +33,7 @@
#include "Types.h" #include "Types.h"
#include "CPU/Bus.h" #include "CPU/Bus.h"
#include "Util/NewConfig.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(int vol)
{
if (vol > 200)
{
ErrorLog("Sound volume cannot exceed 200%%; setting to 100%%.\n");
vol = 100;
}
if (vol < 0)
{
ErrorLog("Sound volume cannot be negative; setting to 0%%.\n");
vol = 0;
}
soundVol = (unsigned) vol;
}
inline unsigned GetSoundVolume(void)
{
return soundVol;
}
// Music (DSB MPEG) volume (0-200)
inline void SetMusicVolume(int vol)
{
if (vol > 200)
{
ErrorLog("Music volume cannot exceed 200%%; setting to 100%%.\n");
vol = 100;
}
if (vol < 0)
{
ErrorLog("Music volume cannot be negative; setting to 0%%.\n");
vol = 0;
}
musicVol = (unsigned) vol;
}
inline unsigned GetMusicVolume(void)
{
return musicVol;
}
// Defaults
CDSBConfig(void)
{
emulateDSB = true;
soundVol = 100;
musicVol = 100;
}
private:
unsigned soundVol;
unsigned musicVol;
};
/****************************************************************************** /******************************************************************************
@ -142,7 +66,12 @@ class CDSBResampler
public: public:
int UpSampleAndMix(INT16 *outL, INT16 *outR, INT16 *inL, INT16 *inR, UINT8 volumeL, UINT8 volumeR, int sizeOut, int sizeIn, int outRate, int inRate); int UpSampleAndMix(INT16 *outL, INT16 *outR, INT16 *inL, INT16 *inR, UINT8 volumeL, UINT8 volumeR, int sizeOut, int sizeIn, int outRate, int inRate);
void Reset(void); void Reset(void);
CDSBResampler(const Util::Config::Node &config)
: m_config(config)
{
}
private: private:
const Util::Config::Node &m_config;
int nFrac; int nFrac;
int pFrac; int pFrac;
}; };
@ -261,10 +190,12 @@ public:
CZ80 *GetZ80(void); CZ80 *GetZ80(void);
// Constructor and destructor // Constructor and destructor
CDSB1(void); CDSB1(const Util::Config::Node &config);
~CDSB1(void); ~CDSB1(void);
private: private:
const Util::Config::Node &m_config;
// Resampler // Resampler
CDSBResampler Resampler; CDSBResampler Resampler;
int retainedSamples; // how many MPEG samples carried over from previous frame int retainedSamples; // how many MPEG samples carried over from previous frame
@ -336,10 +267,12 @@ public:
M68KCtx *GetM68K(void); M68KCtx *GetM68K(void);
// Constructor and destructor // Constructor and destructor
CDSB2(void); CDSB2(const Util::Config::Node &config);
~CDSB2(void); ~CDSB2(void);
private: private:
const Util::Config::Node &m_config;
// Private helper functions // Private helper functions
void WriteMPEGFIFO(UINT8 byte); void WriteMPEGFIFO(UINT8 byte);

File diff suppressed because it is too large Load diff

View file

@ -28,26 +28,7 @@
#ifndef INCLUDED_DRIVEBOARD_H #ifndef INCLUDED_DRIVEBOARD_H
#define INCLUDED_DRIVEBOARD_H #define INCLUDED_DRIVEBOARD_H
/* #include "Util/NewConfig.h"
* CDriveBoardConfig:
*
* Settings used by CDriveBoard.
*/
class CDriveBoardConfig
{
public:
bool forceFeedback; // Enable drive board emulation/simulation (read only during Reset(), cannot be changed in-game)
bool simulateDrvBoard; // Simulate drive board rather than emulating it
unsigned steeringStrength; // Setting for steering strength on DIP switches of drive board
// Defaults
CDriveBoardConfig(void)
{
forceFeedback = false;
simulateDrvBoard = false;
steeringStrength = 5;
}
};
/* /*
* CDriveBoard * CDriveBoard
@ -55,287 +36,292 @@ public:
class CDriveBoard : public IBus class CDriveBoard : public IBus
{ {
public: public:
/* /*
* IsAttached(void): * IsAttached(void):
* *
* Returns: * Returns:
* True if the drive board is "attached" and should be emulated, * True if the drive board is "attached" and should be emulated,
* otherwise false. * otherwise false.
*/ */
bool IsAttached(void); bool IsAttached(void);
/* /*
* IsSimulated(void): * IsSimulated(void):
* *
* Returns: * Returns:
* True if the drive board is being simulated rather than actually * True if the drive board is being simulated rather than actually
* emulated, otherwise false. * emulated, otherwise false.
*/ */
bool IsSimulated(void); bool IsSimulated(void);
/* /*
* GetDIPSwitches(dip1, dip2): * GetDIPSwitches(dip1, dip2):
* *
* Reads the two sets of DIP switches on the drive board. * Reads the two sets of DIP switches on the drive board.
* *
* Parameters: * Parameters:
* dip1 Reference of variable to store DIP switch 1 to. * dip1 Reference of variable to store DIP switch 1 to.
* dip2 DIP switch 2. * dip2 DIP switch 2.
*/ */
void GetDIPSwitches(UINT8 &dip1, UINT8 &dip2); void GetDIPSwitches(UINT8 &dip1, UINT8 &dip2);
/* /*
* SetDIPSwitches(dip1, dip2): * SetDIPSwitches(dip1, dip2):
* *
* Sets the DIP switches. * Sets the DIP switches.
* *
* Parameters: * Parameters:
* dip1 DIP switch 1 value. * dip1 DIP switch 1 value.
* dip2 DIP switch 2 value. * dip2 DIP switch 2 value.
*/ */
void SetDIPSwitches(UINT8 dip1, UINT8 dip2); void SetDIPSwitches(UINT8 dip1, UINT8 dip2);
/* /*
* GetSteeringStrength(void): * GetSteeringStrength(void):
* *
* Returns: * Returns:
* Strength of the steering based on drive board DIP switches (1-8). * Strength of the steering based on drive board DIP switches (1-8).
*/ */
unsigned GetSteeringStrength(void); unsigned GetSteeringStrength(void);
/* /*
* SetSteeringStrength(steeringStrength): * SetSteeringStrength(steeringStrength):
* *
* Sets the steering strength (modifies the DIP switch setting). * Sets the steering strength (modifies the DIP switch setting).
* *
* Parameters: * Parameters:
* steeringStrength A value ranging from 1 to 8. * steeringStrength A value ranging from 1 to 8.
*/ */
void SetSteeringStrength(unsigned steeringStrength); void SetSteeringStrength(unsigned steeringStrength);
/* /*
* Get7SegDisplays(seg1Digit1, seg1Digit2, seg2Digit1, seg2Digit2): * Get7SegDisplays(seg1Digit1, seg1Digit2, seg2Digit1, seg2Digit2):
* *
* Reads the 7-segment displays. * Reads the 7-segment displays.
* *
* Parameters: * Parameters:
* seg1Digit1 Reference of variable to store digit 1 of the first 7- * seg1Digit1 Reference of variable to store digit 1 of the first 7-
* segment display to. * segment display to.
* seg1Digit2 First display, second digit. * seg1Digit2 First display, second digit.
* seg2Digit1 Second display, first digit. * seg2Digit1 Second display, first digit.
* seg2Digit2 Second display, second digit. * seg2Digit2 Second display, second digit.
*/ */
void Get7SegDisplays(UINT8 &seg1Digit, UINT8 &seg1Digit2, UINT8 &seg2Digit1, UINT8 &seg2Digit2); void Get7SegDisplays(UINT8 &seg1Digit, UINT8 &seg1Digit2, UINT8 &seg2Digit1, UINT8 &seg2Digit2);
/* /*
* GetZ80(void): * GetZ80(void):
* *
* Returns: * Returns:
* The Z80 object. * The Z80 object.
*/ */
CZ80 *GetZ80(void); CZ80 *GetZ80(void);
/* /*
* SaveState(SaveState): * SaveState(SaveState):
* *
* Saves the drive board state. * Saves the drive board state.
* *
* Parameters: * Parameters:
* SaveState Block file to save state information to. * SaveState Block file to save state information to.
*/ */
void SaveState(CBlockFile *SaveState); void SaveState(CBlockFile *SaveState);
/* /*
* LoadState(SaveState): * LoadState(SaveState):
* *
* Restores the drive board state. * Restores the drive board state.
* *
* Parameters: * Parameters:
* SaveState Block file to load save state information from. * SaveState Block file to load save state information from.
*/ */
void LoadState(CBlockFile *SaveState); void LoadState(CBlockFile *SaveState);
/* /*
* Init(romPtr): * Init(romPtr):
* *
* Initializes (and "attaches") the drive board. This should be called * Initializes (and "attaches") the drive board. This should be called
* before other members. * before other members.
* *
* Parameters: * Parameters:
* romPtr Pointer to the drive board ROM (Z80 program). If this * romPtr Pointer to the drive board ROM (Z80 program). If this
* is NULL, then the drive board will not be emulated. * is NULL, then the drive board will not be emulated.
* *
* Returns: * Returns:
* FAIL if the drive board could not be initialized (prints own error * FAIL if the drive board could not be initialized (prints own error
* message), otherwise OKAY. If the drive board is not attached * message), otherwise OKAY. If the drive board is not attached
* because no ROM was passed to it, no error is generated and the * because no ROM was passed to it, no error is generated and the
* drive board is silently disabled (detached). * drive board is silently disabled (detached).
*/ */
bool Init(const UINT8 *romPtr); bool Init(const UINT8 *romPtr);
/* /*
* AttachInputs(InputsPtr, gameInputFlags): * AttachInputs(InputsPtr, gameInputFlags):
* *
* Attaches inputs to the drive board (for access to the steering wheel * Attaches inputs to the drive board (for access to the steering wheel
* position). * position).
* *
* Parameters: * Parameters:
* inputs Pointer to the input object. * inputs Pointer to the input object.
* gameInputFlags The current game's input flags. * gameInputFlags The current game's input flags.
*/ */
void AttachInputs(CInputs *inputs, unsigned gameInputFlags); void AttachInputs(CInputs *inputs, unsigned gameInputFlags);
void AttachOutputs(COutputs *outputs); void AttachOutputs(COutputs *outputs);
/* /*
* Reset(void): * Reset(void):
* *
* Resets the drive board. * Resets the drive board.
*/ */
void Reset(void); void Reset(void);
/* /*
* Read(): * Read():
* *
* Reads data from the drive board. * Reads data from the drive board.
* *
* Returns: * Returns:
* Data read. * Data read.
*/ */
UINT8 Read(void); UINT8 Read(void);
/* /*
* Write(data): * Write(data):
* *
* Writes data to the drive board. * Writes data to the drive board.
* *
* Parameters: * Parameters:
* data Data to send. * data Data to send.
*/ */
void Write(UINT8 data); void Write(UINT8 data);
/* /*
* RunFrame(void): * RunFrame(void):
* *
* Emulates a single frame's worth of time on the drive board. * Emulates a single frame's worth of time on the drive board.
*/ */
void RunFrame(void); void RunFrame(void);
/* /*
* CDriveBoard(): * CDriveBoard(config):
* ~CDriveBoard(): * ~CDriveBoard():
* *
* Constructor and destructor. Memory is freed by destructor. * Constructor and destructor. Memory is freed by destructor.
*/ *
CDriveBoard(); * Paramters:
~CDriveBoard(void); * config Run-time configuration. The reference should be held because
* this changes at run-time.
*/
CDriveBoard(const Util::Config::Node &config);
~CDriveBoard(void);
/* /*
* Read8(addr): * Read8(addr):
* IORead8(portNum): * IORead8(portNum):
* *
* Methods for reading from Z80's memory and IO space. Required by CBus. * Methods for reading from Z80's memory and IO space. Required by CBus.
* *
* Parameters: * Parameters:
* addr Address in memory (0-0xFFFF). * addr Address in memory (0-0xFFFF).
* portNum Port address (0-255). * portNum Port address (0-255).
* *
* Returns: * Returns:
* A byte of data from the address or port. * A byte of data from the address or port.
*/ */
UINT8 Read8(UINT32 addr); UINT8 Read8(UINT32 addr);
UINT8 IORead8(UINT32 portNum); UINT8 IORead8(UINT32 portNum);
/* /*
* Write8(addr, data): * Write8(addr, data):
* IORead8(portNum, data): * IORead8(portNum, data):
* *
* Methods for writing to Z80's memory and IO space. Required by CBus. * Methods for writing to Z80's memory and IO space. Required by CBus.
* *
* Parameters: * Parameters:
* addr Address in memory (0-0xFFFF). * addr Address in memory (0-0xFFFF).
* portNum Port address (0-255). * portNum Port address (0-255).
* data Byte to write. * data Byte to write.
*/ */
void Write8(UINT32 addr, UINT8 data); void Write8(UINT32 addr, UINT8 data);
void IOWrite8(UINT32 portNum, UINT8 data); void IOWrite8(UINT32 portNum, UINT8 data);
private: private:
bool m_attached; // True if drive board is attached const Util::Config::Node &m_config;
bool m_tmpDisabled; // True if temporarily disabled by loading an incompatible save state bool m_attached; // True if drive board is attached
bool m_simulated; // True if drive board should be simulated rather than emulated bool m_tmpDisabled; // True if temporarily disabled by loading an incompatible save state
bool m_simulated; // True if drive board should be simulated rather than emulated
UINT8 m_dip1; // Value of DIP switch 1 UINT8 m_dip1; // Value of DIP switch 1
UINT8 m_dip2; // Value of DIP switch 2 UINT8 m_dip2; // Value of DIP switch 2
const UINT8* m_rom; // 32k ROM const UINT8* m_rom; // 32k ROM
UINT8* m_ram; // 8k RAM UINT8* m_ram; // 8k RAM
CZ80 m_z80; // Z80 CPU @ 4MHz CZ80 m_z80; // Z80 CPU @ 4MHz
CInputs *m_inputs; CInputs *m_inputs;
unsigned m_inputFlags; unsigned m_inputFlags;
COutputs *m_outputs; COutputs *m_outputs;
// Emulation state // Emulation state
bool m_initialized; // True if drive board has finished initialization bool m_initialized; // True if drive board has finished initialization
bool m_allowInterrupts; // True if drive board has enabled NMI interrupts bool m_allowInterrupts; // True if drive board has enabled NMI interrupts
UINT8 m_seg1Digit1; // Current value of left digit on 7-segment display 1 UINT8 m_seg1Digit1; // Current value of left digit on 7-segment display 1
UINT8 m_seg1Digit2; // Current value of right digit on 7-segment display 1 UINT8 m_seg1Digit2; // Current value of right digit on 7-segment display 1
UINT8 m_seg2Digit1; // Current value of left digit on 7-segment display 2 UINT8 m_seg2Digit1; // Current value of left digit on 7-segment display 2
UINT8 m_seg2Digit2; // Current value of right digit on 7-segment display 2 UINT8 m_seg2Digit2; // Current value of right digit on 7-segment display 2
UINT8 m_dataSent; // Last command sent by main board UINT8 m_dataSent; // Last command sent by main board
UINT8 m_dataReceived; // Data to send back to main board UINT8 m_dataReceived; // Data to send back to main board
UINT16 m_adcPortRead; // ADC port currently reading from UINT16 m_adcPortRead; // ADC port currently reading from
UINT8 m_adcPortBit; // Bit number currently reading on ADC port UINT8 m_adcPortBit; // Bit number currently reading on ADC port
UINT8 m_port42Out; // Last value sent to Z80 I/O port 42 (encoder motor data) UINT8 m_port42Out; // Last value sent to Z80 I/O port 42 (encoder motor data)
UINT8 m_port46Out; // Last value sent to Z80 I/O port 46 (encoder motor control) UINT8 m_port46Out; // Last value sent to Z80 I/O port 46 (encoder motor control)
UINT8 m_prev42Out; // Previous value sent to Z80 I/O port 42 UINT8 m_prev42Out; // Previous value sent to Z80 I/O port 42
UINT8 m_prev46Out; // Previous value sent to Z80 I/O port 46 UINT8 m_prev46Out; // Previous value sent to Z80 I/O port 46
UINT8 m_uncenterVal1; // First part of pending uncenter command UINT8 m_uncenterVal1; // First part of pending uncenter command
UINT8 m_uncenterVal2; // Second part of pending uncenter command UINT8 m_uncenterVal2; // Second part of pending uncenter command
// Simulation state // Simulation state
UINT8 m_initState; UINT8 m_initState;
UINT8 m_statusFlags; UINT8 m_statusFlags;
UINT8 m_boardMode; UINT8 m_boardMode;
UINT8 m_readMode; UINT8 m_readMode;
UINT8 m_wheelCenter; UINT8 m_wheelCenter;
UINT8 m_cockpitCenter; UINT8 m_cockpitCenter;
UINT8 m_echoVal; UINT8 m_echoVal;
// Feedback state // Feedback state
INT8 m_lastConstForce; // Last constant force command sent INT8 m_lastConstForce; // Last constant force command sent
UINT8 m_lastSelfCenter; // Last self center command sent UINT8 m_lastSelfCenter; // Last self center command sent
UINT8 m_lastFriction; // Last friction command sent UINT8 m_lastFriction; // Last friction command sent
UINT8 m_lastVibrate; // Last vibrate command sent UINT8 m_lastVibrate; // Last vibrate command sent
UINT8 SimulateRead(void); UINT8 SimulateRead(void);
void SimulateWrite(UINT8 data); void SimulateWrite(UINT8 data);
void SimulateFrame(void); void SimulateFrame(void);
void EmulateFrame(void); void EmulateFrame(void);
void ProcessEncoderCmd(void); void ProcessEncoderCmd(void);
void SendStopAll(void); void SendStopAll(void);
void SendConstantForce(INT8 val); void SendConstantForce(INT8 val);
void SendSelfCenter(UINT8 val); void SendSelfCenter(UINT8 val);
void SendFriction(UINT8 val); void SendFriction(UINT8 val);
void SendVibrate(UINT8 val); void SendVibrate(UINT8 val);
}; };
#endif // INCLUDED_DRIVEBOARD_H #endif // INCLUDED_DRIVEBOARD_H

View file

@ -30,7 +30,8 @@
#define INCLUDED_IEMULATOR_H #define INCLUDED_IEMULATOR_H
class CBlockFile; class CBlockFile;
struct GameInfo; struct Game;
struct ROMSet;
class CRender2D; class CRender2D;
class IRender3D; class IRender3D;
class CInputs; class CInputs;
@ -116,31 +117,30 @@ public:
* Resets the system. Does not modify non-volatile memory. * Resets the system. Does not modify non-volatile memory.
*/ */
virtual void Reset(void) = 0; virtual void Reset(void) = 0;
/* /*
* GetGameInfo(void): * GetGame(void):
* *
* Returns: * Returns:
* A pointer to the presently loaded game's information structure (or * A reference to the presently loaded game's information structure (which
* NULL if no ROM set has yet been loaded). * will be blank if no game has yet been loaded).
*/ */
virtual const struct GameInfo * GetGameInfo(void) = 0; virtual const Game &GetGame(void) const = 0;
/* /*
* LoadROMSet(GameList, zipFile): * LoadGame(game, rom_set):
* *
* Loads a complete ROM set from the specified ZIP archive. * Loads a game, copying in the provided ROMs and setting the hardware
* stepping.
* *
* NOTE: Command line settings will not have been applied here yet. * Parameters:
* * game Game information.
* Parameters: * rom_set ROMs.
* GameList List of all supported games and their ROMs.
* zipFile ZIP file to load from.
* *
* Returns: * Returns:
* OKAY if successful, FAIL otherwise. Prints errors. * OKAY if successful, FAIL otherwise. Prints errors.
*/ */
virtual bool LoadROMSet(const struct GameInfo *GameList, const char *zipFile) = 0; virtual bool LoadGame(const Game &game, const ROMSet &rom_set) = 0;
/* /*
* AttachRenderers(Render2DPtr, Render3DPtr): * AttachRenderers(Render2DPtr, Render3DPtr):

View file

@ -202,10 +202,13 @@
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include "Supermodel.h" #include "Supermodel.h"
#include "Game.h"
#include "ROMSet.h"
#include "Util/Format.h" #include "Util/Format.h"
#include "Util/ByteSwap.h"
#include <functional> #include <functional>
#include <set> #include <set>
#include <sstream> #include <iostream>
/****************************************************************************** /******************************************************************************
Model 3 Inputs Model 3 Inputs
@ -244,7 +247,7 @@ UINT8 CModel3::ReadInputs(unsigned reg)
data = (data&0xDF)|(EEPROM.Read()<<5); // bank 1 contains EEPROM data bit data = (data&0xDF)|(EEPROM.Read()<<5); // bank 1 contains EEPROM data bit
} }
if ((Game->inputFlags&GAME_INPUT_SKI)) if ((m_game.inputs & Game::INPUT_SKI))
{ {
if ((inputBank&1) == 0) if ((inputBank&1) == 0)
{ {
@ -261,12 +264,12 @@ UINT8 CModel3::ReadInputs(unsigned reg)
data = 0xFF; data = 0xFF;
if ((Game->inputFlags&GAME_INPUT_SKI)) if ((m_game.inputs & Game::INPUT_SKI))
{ {
data &= ~(Inputs->skiPollRight->value<<0); data &= ~(Inputs->skiPollRight->value<<0);
} }
if ((Game->inputFlags&GAME_INPUT_JOYSTICK1)) if ((m_game.inputs & Game::INPUT_JOYSTICK1))
{ {
data &= ~(Inputs->up[0]->value<<5); // P1 Up data &= ~(Inputs->up[0]->value<<5); // P1 Up
data &= ~(Inputs->down[0]->value<<4); // P1 Down data &= ~(Inputs->down[0]->value<<4); // P1 Down
@ -274,7 +277,7 @@ UINT8 CModel3::ReadInputs(unsigned reg)
data &= ~(Inputs->right[0]->value<<6); // P1 Right data &= ~(Inputs->right[0]->value<<6); // P1 Right
} }
if ((Game->inputFlags&GAME_INPUT_FIGHTING)) if ((m_game.inputs & Game::INPUT_FIGHTING))
{ {
data &= ~(Inputs->escape[0]->value<<3); // P1 Escape data &= ~(Inputs->escape[0]->value<<3); // P1 Escape
data &= ~(Inputs->guard[0]->value<<2); // P1 Guard data &= ~(Inputs->guard[0]->value<<2); // P1 Guard
@ -282,7 +285,7 @@ UINT8 CModel3::ReadInputs(unsigned reg)
data &= ~(Inputs->punch[0]->value<<0); // P1 Punch data &= ~(Inputs->punch[0]->value<<0); // P1 Punch
} }
if ((Game->inputFlags&GAME_INPUT_SPIKEOUT)) if ((m_game.inputs & Game::INPUT_SPIKEOUT))
{ {
data &= ~(Inputs->shift->value<<2); // Shift data &= ~(Inputs->shift->value<<2); // Shift
data &= ~(Inputs->beat->value<<0); // Beat data &= ~(Inputs->beat->value<<0); // Beat
@ -290,14 +293,14 @@ UINT8 CModel3::ReadInputs(unsigned reg)
data &= ~(Inputs->jump->value<<3); // Jump data &= ~(Inputs->jump->value<<3); // Jump
} }
if ((Game->inputFlags&GAME_INPUT_SOCCER)) if ((m_game.inputs & Game::INPUT_SOCCER))
{ {
data &= ~(Inputs->shortPass[0]->value<<2); // P1 Short Pass data &= ~(Inputs->shortPass[0]->value<<2); // P1 Short Pass
data &= ~(Inputs->longPass[0]->value<<0); // P1 Long Pass data &= ~(Inputs->longPass[0]->value<<0); // P1 Long Pass
data &= ~(Inputs->shoot[0]->value<<1); // P1 Shoot data &= ~(Inputs->shoot[0]->value<<1); // P1 Shoot
} }
if ((Game->inputFlags&GAME_INPUT_VR4)) if ((m_game.inputs & Game::INPUT_VR4))
{ {
data &= ~(Inputs->vr[0]->value<<0); // VR1 Red data &= ~(Inputs->vr[0]->value<<0); // VR1 Red
data &= ~(Inputs->vr[1]->value<<1); // VR2 Blue data &= ~(Inputs->vr[1]->value<<1); // VR2 Blue
@ -305,16 +308,16 @@ UINT8 CModel3::ReadInputs(unsigned reg)
data &= ~(Inputs->vr[3]->value<<3); // VR4 Green data &= ~(Inputs->vr[3]->value<<3); // VR4 Green
} }
if ((Game->inputFlags&GAME_INPUT_VIEWCHANGE)) if ((m_game.inputs & Game::INPUT_VIEWCHANGE))
{ {
// Harley is wired slightly differently // Harley is wired slightly differently
if ((Game->inputFlags&GAME_INPUT_HARLEY)) if ((m_game.inputs & Game::INPUT_HARLEY))
data &= ~(Inputs->viewChange->value<<1); // View change data &= ~(Inputs->viewChange->value<<1); // View change
else else
data &= ~(Inputs->viewChange->value<<0); // View change data &= ~(Inputs->viewChange->value<<0); // View change
} }
if ((Game->inputFlags&GAME_INPUT_SHIFT4)) if ((m_game.inputs & Game::INPUT_SHIFT4))
{ {
if (Inputs->gearShift4->value == 2) // Shift 2 if (Inputs->gearShift4->value == 2) // Shift 2
data &= ~0x60; data &= ~0x60;
@ -326,10 +329,10 @@ UINT8 CModel3::ReadInputs(unsigned reg)
data &= ~0x10; data &= ~0x10;
} }
if ((Game->inputFlags&GAME_INPUT_SHIFTUPDOWN)) if ((m_game.inputs & Game::INPUT_SHIFTUPDOWN))
{ {
// Harley is wired slightly differently // Harley is wired slightly differently
if ((Game->inputFlags&GAME_INPUT_HARLEY)) if ((m_game.inputs & Game::INPUT_HARLEY))
{ {
if (Inputs->gearShiftUp->value) // Shift up if (Inputs->gearShiftUp->value) // Shift up
data &= ~0x60; data &= ~0x60;
@ -345,16 +348,16 @@ UINT8 CModel3::ReadInputs(unsigned reg)
} }
} }
if ((Game->inputFlags&GAME_INPUT_HANDBRAKE)) if ((m_game.inputs & Game::INPUT_HANDBRAKE))
data &= ~(Inputs->handBrake->value<<1); // Hand brake data &= ~(Inputs->handBrake->value<<1); // Hand brake
if ((Game->inputFlags&GAME_INPUT_HARLEY)) if ((m_game.inputs & Game::INPUT_HARLEY))
data &= ~(Inputs->musicSelect->value<<0); // Music select data &= ~(Inputs->musicSelect->value<<0); // Music select
if ((Game->inputFlags&GAME_INPUT_GUN1)) if ((m_game.inputs & Game::INPUT_GUN1))
data &= ~(Inputs->trigger[0]->value<<0); // P1 Trigger data &= ~(Inputs->trigger[0]->value<<0); // P1 Trigger
if ((Game->inputFlags&GAME_INPUT_ANALOG_JOYSTICK)) if ((m_game.inputs & Game::INPUT_ANALOG_JOYSTICK))
{ {
data &= ~(Inputs->analogJoyTrigger1->value<<5); // Trigger 1 data &= ~(Inputs->analogJoyTrigger1->value<<5); // Trigger 1
data &= ~(Inputs->analogJoyTrigger2->value<<4); // Trigger 2 data &= ~(Inputs->analogJoyTrigger2->value<<4); // Trigger 2
@ -362,7 +365,7 @@ UINT8 CModel3::ReadInputs(unsigned reg)
data &= ~(Inputs->analogJoyEvent2->value<<1); // Event Button 2 data &= ~(Inputs->analogJoyEvent2->value<<1); // Event Button 2
} }
if ((Game->inputFlags&GAME_INPUT_TWIN_JOYSTICKS)) // First twin joystick if ((m_game.inputs & Game::INPUT_TWIN_JOYSTICKS)) // First twin joystick
{ {
/* /*
* Process left joystick inputs first * Process left joystick inputs first
@ -418,16 +421,16 @@ UINT8 CModel3::ReadInputs(unsigned reg)
data &= ~0x40; data &= ~0x40;
} }
if ((Game->inputFlags&GAME_INPUT_ANALOG_GUN1)) if ((m_game.inputs & Game::INPUT_ANALOG_GUN1))
{ {
data &= ~(Inputs->analogTriggerLeft[0]->value<<0); data &= ~(Inputs->analogTriggerLeft[0]->value<<0);
data &= ~(Inputs->analogTriggerRight[0]->value<<1); data &= ~(Inputs->analogTriggerRight[0]->value<<1);
} }
if ((Game->inputFlags & GAME_INPUT_MAGTRUCK)) if ((m_game.inputs & Game::INPUT_MAGTRUCK))
data &= ~(Inputs->magicalPedal1->value << 0); data &= ~(Inputs->magicalPedal1->value << 0);
if ((Game->inputFlags & GAME_INPUT_FISHING)) if ((m_game.inputs & Game::INPUT_FISHING))
{ {
data &= ~(Inputs->fishingCast->value << 0); data &= ~(Inputs->fishingCast->value << 0);
data &= ~(Inputs->fishingSelect->value << 1); data &= ~(Inputs->fishingSelect->value << 1);
@ -441,7 +444,7 @@ UINT8 CModel3::ReadInputs(unsigned reg)
if (DriveBoard.IsAttached()) if (DriveBoard.IsAttached())
data = DriveBoard.Read(); data = DriveBoard.Read();
if ((Game->inputFlags&GAME_INPUT_JOYSTICK2)) if ((m_game.inputs & Game::INPUT_JOYSTICK2))
{ {
data &= ~(Inputs->up[1]->value<<5); // P2 Up data &= ~(Inputs->up[1]->value<<5); // P2 Up
data &= ~(Inputs->down[1]->value<<4); // P2 Down data &= ~(Inputs->down[1]->value<<4); // P2 Down
@ -449,7 +452,7 @@ UINT8 CModel3::ReadInputs(unsigned reg)
data &= ~(Inputs->right[1]->value<<6); // P2 Right data &= ~(Inputs->right[1]->value<<6); // P2 Right
} }
if ((Game->inputFlags&GAME_INPUT_FIGHTING)) if ((m_game.inputs & Game::INPUT_FIGHTING))
{ {
data &= ~(Inputs->escape[1]->value<<3); // P2 Escape data &= ~(Inputs->escape[1]->value<<3); // P2 Escape
data &= ~(Inputs->guard[1]->value<<2); // P2 Guard data &= ~(Inputs->guard[1]->value<<2); // P2 Guard
@ -457,14 +460,14 @@ UINT8 CModel3::ReadInputs(unsigned reg)
data &= ~(Inputs->punch[1]->value<<0); // P2 Punch data &= ~(Inputs->punch[1]->value<<0); // P2 Punch
} }
if ((Game->inputFlags&GAME_INPUT_SOCCER)) if ((m_game.inputs & Game::INPUT_SOCCER))
{ {
data &= ~(Inputs->shortPass[1]->value<<2); // P2 Short Pass data &= ~(Inputs->shortPass[1]->value<<2); // P2 Short Pass
data &= ~(Inputs->longPass[1]->value<<0); // P2 Long Pass data &= ~(Inputs->longPass[1]->value<<0); // P2 Long Pass
data &= ~(Inputs->shoot[1]->value<<1); // P2 Shoot data &= ~(Inputs->shoot[1]->value<<1); // P2 Shoot
} }
if ((Game->inputFlags&GAME_INPUT_TWIN_JOYSTICKS)) // Second twin joystick (see register 0x08 for comments) if ((m_game.inputs & Game::INPUT_TWIN_JOYSTICKS)) // Second twin joystick (see register 0x08 for comments)
{ {
data &= ~(Inputs->twinJoyShot2->value<<0); data &= ~(Inputs->twinJoyShot2->value<<0);
@ -494,16 +497,16 @@ UINT8 CModel3::ReadInputs(unsigned reg)
data &= ~0x80; data &= ~0x80;
} }
if ((Game->inputFlags&GAME_INPUT_GUN2)) if ((m_game.inputs & Game::INPUT_GUN2))
data &= ~(Inputs->trigger[1]->value<<0); // P2 Trigger data &= ~(Inputs->trigger[1]->value<<0); // P2 Trigger
if ((Game->inputFlags&GAME_INPUT_ANALOG_GUN2)) if ((m_game.inputs & Game::INPUT_ANALOG_GUN2))
{ {
data &= ~(Inputs->analogTriggerLeft[1]->value<<0); data &= ~(Inputs->analogTriggerLeft[1]->value<<0);
data &= ~(Inputs->analogTriggerRight[1]->value<<1); data &= ~(Inputs->analogTriggerRight[1]->value<<1);
} }
if ((Game->inputFlags & GAME_INPUT_MAGTRUCK)) if ((m_game.inputs & Game::INPUT_MAGTRUCK))
data &= ~(Inputs->magicalPedal2->value << 0); data &= ~(Inputs->magicalPedal2->value << 0);
return data; return data;
@ -521,22 +524,22 @@ UINT8 CModel3::ReadInputs(unsigned reg)
// Load ADC channels with input data // Load ADC channels with input data
memset(adc, 0, sizeof(adc)); memset(adc, 0, sizeof(adc));
if ((Game->inputFlags&GAME_INPUT_VEHICLE)) if ((m_game.inputs & Game::INPUT_VEHICLE))
{ {
adc[0] = (UINT8)Inputs->steering->value; adc[0] = (UINT8)Inputs->steering->value;
adc[1] = (UINT8)Inputs->accelerator->value; adc[1] = (UINT8)Inputs->accelerator->value;
adc[2] = (UINT8)Inputs->brake->value; adc[2] = (UINT8)Inputs->brake->value;
if ((Game->inputFlags&GAME_INPUT_HARLEY)) if ((m_game.inputs & Game::INPUT_HARLEY))
adc[3] = (UINT8)Inputs->rearBrake->value; adc[3] = (UINT8)Inputs->rearBrake->value;
} }
if ((Game->inputFlags&GAME_INPUT_ANALOG_JOYSTICK)) if ((m_game.inputs & Game::INPUT_ANALOG_JOYSTICK))
{ {
adc[0] = (UINT8)Inputs->analogJoyY->value; adc[0] = (UINT8)Inputs->analogJoyY->value;
adc[1] = (UINT8)Inputs->analogJoyX->value; adc[1] = (UINT8)Inputs->analogJoyX->value;
} }
if ((Game->inputFlags&GAME_INPUT_ANALOG_GUN1)||(Game->inputFlags&GAME_INPUT_ANALOG_GUN2)) if ((m_game.inputs & Game::INPUT_ANALOG_GUN1)||(m_game.inputs & Game::INPUT_ANALOG_GUN2))
{ {
adc[0] = (UINT8)Inputs->analogGunX[0]->value; adc[0] = (UINT8)Inputs->analogGunX[0]->value;
adc[2] = (UINT8)Inputs->analogGunY[0]->value; adc[2] = (UINT8)Inputs->analogGunY[0]->value;
@ -544,19 +547,19 @@ UINT8 CModel3::ReadInputs(unsigned reg)
adc[3] = (UINT8)Inputs->analogGunY[1]->value; adc[3] = (UINT8)Inputs->analogGunY[1]->value;
} }
if ((Game->inputFlags&GAME_INPUT_SKI)) if ((m_game.inputs & Game::INPUT_SKI))
{ {
adc[0] = (UINT8)Inputs->skiY->value; adc[0] = (UINT8)Inputs->skiY->value;
adc[1] = (UINT8)Inputs->skiX->value; adc[1] = (UINT8)Inputs->skiX->value;
} }
if ((Game->inputFlags & GAME_INPUT_MAGTRUCK)) if ((m_game.inputs & Game::INPUT_MAGTRUCK))
{ {
adc[0] = uint8_t(Inputs->magicalLever1->value); adc[0] = uint8_t(Inputs->magicalLever1->value);
adc[1] = uint8_t(Inputs->magicalLever2->value); adc[1] = uint8_t(Inputs->magicalLever2->value);
} }
if ((Game->inputFlags & GAME_INPUT_FISHING)) if ((m_game.inputs & Game::INPUT_FISHING))
{ {
adc[0] = uint8_t(Inputs->fishingRodY->value); adc[0] = uint8_t(Inputs->fishingRodY->value);
adc[1] = uint8_t(Inputs->fishingRodX->value); adc[1] = uint8_t(Inputs->fishingRodX->value);
@ -615,7 +618,7 @@ void CModel3::WriteInputs(unsigned reg, UINT8 data)
case 0x87: // Read light gun register case 0x87: // Read light gun register
serialFIFO1 = 0; // clear serial FIFO 1 serialFIFO1 = 0; // clear serial FIFO 1
serialFIFO2 = 0; serialFIFO2 = 0;
if ((Game->inputFlags&GAME_INPUT_GUN1||Game->inputFlags&GAME_INPUT_GUN2)) if ((m_game.inputs & Game::INPUT_GUN1||m_game.inputs & Game::INPUT_GUN2))
{ {
switch (gunReg) switch (gunReg)
{ {
@ -940,7 +943,7 @@ UINT8 CModel3::Read8(UINT32 addr)
// 53C810 SCSI // 53C810 SCSI
case 0xC0: // only on Step 1.0 case 0xC0: // only on Step 1.0
if (Game->step != 0x10) if (m_game.stepping != "1.0")
break; break;
case 0xF9: case 0xF9:
case 0xC1: case 0xC1:
@ -1174,7 +1177,7 @@ UINT32 CModel3::Read32(UINT32 addr)
// 53C810 SCSI // 53C810 SCSI
case 0xC0: // only on Step 1.0 case 0xC0: // only on Step 1.0
if (Game->step != 0x10) // check for Step 1.0 if (m_game.stepping != "1.0") // check for Step 1.0
break; break;
case 0xF9: case 0xF9:
case 0xC1: case 0xC1:
@ -1291,7 +1294,7 @@ void CModel3::Write8(UINT32 addr, UINT8 data)
// 53C810 SCSI // 53C810 SCSI
case 0xC0: // only on Step 1.0 case 0xC0: // only on Step 1.0
if (Game->step != 0x10) if (m_game.stepping != "1.0")
goto Unknown8; goto Unknown8;
case 0xF9: case 0xF9:
case 0xC1: case 0xC1:
@ -1553,7 +1556,7 @@ void CModel3::Write32(UINT32 addr, UINT32 data)
// 53C810 SCSI // 53C810 SCSI
case 0xC0: // step 1.0 only case 0xC0: // step 1.0 only
if (Game->step != 0x10) if (m_game.stepping != "1.0")
goto Unknown32; goto Unknown32;
case 0xF9: case 0xF9:
case 0xC1: case 0xC1:
@ -1687,20 +1690,20 @@ void CModel3::RunFrame(void)
UINT32 start = CThread::GetTicks(); UINT32 start = CThread::GetTicks();
// See if currently running multi-threaded // See if currently running multi-threaded
if (g_Config.multiThreaded) if (m_multiThreaded)
{ {
// If so, check all threads are up and running // If so, check all threads are up and running
if (!StartThreads()) if (!StartThreads())
goto ThreadError; goto ThreadError;
// Wake threads for PPC main board (if multi-threading GPU), sound board (if sync'd) and drive board (if attached) so they can process a frame // Wake threads for PPC main board (if multi-threading GPU), sound board (if sync'd) and drive board (if attached) so they can process a frame
if ((g_Config.gpuMultiThreaded && !ppcBrdThreadSync->Post()) || if ((m_gpuMultiThreaded && !ppcBrdThreadSync->Post()) ||
(syncSndBrdThread && !sndBrdThreadSync->Post()) || (syncSndBrdThread && !sndBrdThreadSync->Post()) ||
(DriveBoard.IsAttached() && !drvBrdThreadSync->Post())) (DriveBoard.IsAttached() && !drvBrdThreadSync->Post()))
goto ThreadError; goto ThreadError;
// If not multi-threading GPU, then run PPC main board for a frame and sync GPUs now in this thread // If not multi-threading GPU, then run PPC main board for a frame and sync GPUs now in this thread
if (!g_Config.gpuMultiThreaded) if (!m_gpuMultiThreaded)
{ {
RunMainBoardFrame(); RunMainBoardFrame();
SyncGPUs(); SyncGPUs();
@ -1714,9 +1717,9 @@ void CModel3::RunFrame(void)
goto ThreadError; goto ThreadError;
// Wait for PPC main board, sound board and drive board threads to finish their work (if they are running and haven't finished already) // Wait for PPC main board, sound board and drive board threads to finish their work (if they are running and haven't finished already)
while ((g_Config.gpuMultiThreaded && !ppcBrdThreadDone) || while ((m_gpuMultiThreaded && !ppcBrdThreadDone) ||
(syncSndBrdThread && !sndBrdThreadDone) || (syncSndBrdThread && !sndBrdThreadDone) ||
(DriveBoard.IsAttached() && !drvBrdThreadDone)) (DriveBoard.IsAttached() && !drvBrdThreadDone))
{ {
if (!notifySync->Wait(notifyLock)) if (!notifySync->Wait(notifyLock))
goto ThreadError; goto ThreadError;
@ -1730,7 +1733,7 @@ void CModel3::RunFrame(void)
goto ThreadError; goto ThreadError;
// If multi-threading GPU, then sync GPUs last while PPC main board thread is waiting // If multi-threading GPU, then sync GPUs last while PPC main board thread is waiting
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
SyncGPUs(); SyncGPUs();
} }
else else
@ -1750,7 +1753,7 @@ void CModel3::RunFrame(void)
ThreadError: ThreadError:
ErrorLog("Threading error in CModel3::RunFrame: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError()); ErrorLog("Threading error in CModel3::RunFrame: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
g_Config.multiThreaded = false; m_multiThreaded = false;
} }
void CModel3::RunMainBoardFrame(void) void CModel3::RunMainBoardFrame(void)
@ -1758,7 +1761,7 @@ void CModel3::RunMainBoardFrame(void)
UINT32 start = CThread::GetTicks(); UINT32 start = CThread::GetTicks();
// Compute display and VBlank timings // Compute display and VBlank timings
unsigned ppcCycles = g_Config.GetPowerPCFrequency() * 1000000; unsigned ppcCycles = m_config["PowerPCFrequency"].ValueAs<unsigned>() * 1000000;
unsigned frameCycles = ppcCycles / 60; unsigned frameCycles = ppcCycles / 60;
unsigned vblCycles = (unsigned)((float) frameCycles * 2.5f/100.0f); // 2.5% vblank (ridiculously short and wrong but bigger values cause flicker in Daytona) unsigned vblCycles = (unsigned)((float) frameCycles * 2.5f/100.0f); // 2.5% vblank (ridiculously short and wrong but bigger values cause flicker in Daytona)
unsigned dispCycles = frameCycles - vblCycles; unsigned dispCycles = frameCycles - vblCycles;
@ -1774,15 +1777,15 @@ void CModel3::RunMainBoardFrame(void)
// The values below were arrived at by trial and error and clearly more investigation is required. If it turns out that the status bit is // The values below were arrived at by trial and error and clearly more investigation is required. If it turns out that the status bit is
// connected to the end of VBlank then the code below should be removed and the timing handled via GPU.VBlankEnd() instead. // connected to the end of VBlank then the code below should be removed and the timing handled via GPU.VBlankEnd() instead.
unsigned statusCycles; unsigned statusCycles;
if (Game->step >= 0x20) if (m_game.stepping == "2.0" || m_game.stepping == "2.1")
{ {
// For some reason, Fighting Vipers 2 and Daytona USA 2 require completely different timing to the rest of the step 2.x games // For some reason, Fighting Vipers 2 and Daytona USA 2 require completely different timing to the rest of the step 2.x games
if (!strcmp(Game->id, "daytona2") || (Game->step == 0x20 && !strcmp(Game->id, "fvipers2"))) if (m_game.name == "daytona2" || (m_game.stepping == "2.0" && m_game.name == "fvipers2"))
statusCycles = (unsigned)((float)frameCycles * 24.0f/100.0f); statusCycles = (unsigned)((float)frameCycles * 24.0f/100.0f);
else else
statusCycles = (unsigned)((float)frameCycles * 9.12f/100.0f); statusCycles = (unsigned)((float)frameCycles * 9.12f/100.0f);
} }
else if (Game->step == 0x15) else if (m_game.stepping == "1.5")
statusCycles = (unsigned)((float)frameCycles * 5.5f/100.0f); statusCycles = (unsigned)((float)frameCycles * 5.5f/100.0f);
else else
statusCycles = (unsigned)((float)frameCycles * 48.0f/100.0f); statusCycles = (unsigned)((float)frameCycles * 48.0f/100.0f);
@ -1905,7 +1908,7 @@ bool CModel3::StartThreads(void)
return true; return true;
// Create synchronization objects // Create synchronization objects
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
{ {
ppcBrdThreadSync = CThread::CreateSemaphore(0); ppcBrdThreadSync = CThread::CreateSemaphore(0);
if (ppcBrdThreadSync == NULL) if (ppcBrdThreadSync == NULL)
@ -1938,7 +1941,7 @@ bool CModel3::StartThreads(void)
stopThreads = false; stopThreads = false;
// Create PPC main board thread, if multi-threading GPU // Create PPC main board thread, if multi-threading GPU
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
{ {
ppcBrdThread = CThread::CreateThread(StartMainBoardThread, this); ppcBrdThread = CThread::CreateThread(StartMainBoardThread, this);
if (ppcBrdThread == NULL) if (ppcBrdThread == NULL)
@ -1971,7 +1974,7 @@ bool CModel3::StartThreads(void)
ThreadError: ThreadError:
ErrorLog("Unable to create threads and/or synchronization objects: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError()); ErrorLog("Unable to create threads and/or synchronization objects: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
DeleteThreadObjects(); DeleteThreadObjects();
g_Config.multiThreaded = false; m_multiThreaded = false;
return false; return false;
} }
@ -1999,7 +2002,7 @@ bool CModel3::PauseThreads(void)
ThreadError: ThreadError:
ErrorLog("Threading error in CModel3::PauseThreads: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError()); ErrorLog("Threading error in CModel3::PauseThreads: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
g_Config.multiThreaded = false; m_multiThreaded = false;
return false; return false;
} }
@ -2022,7 +2025,7 @@ bool CModel3::ResumeThreads(void)
ThreadError: ThreadError:
ErrorLog("Threading error in CModel3::ResumeThreads: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError()); ErrorLog("Threading error in CModel3::ResumeThreads: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
g_Config.multiThreaded = false; m_multiThreaded = false;
return false; return false;
} }
@ -2086,7 +2089,7 @@ bool CModel3::StopThreads(void)
ThreadError: ThreadError:
ErrorLog("Threading error in CModel3::StopThreads: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError()); ErrorLog("Threading error in CModel3::StopThreads: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
g_Config.multiThreaded = false; m_multiThreaded = false;
return false; return false;
} }
@ -2244,7 +2247,7 @@ int CModel3::RunMainBoardThread(void)
ThreadError: ThreadError:
ErrorLog("Threading error in RunMainBoardThread: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError()); ErrorLog("Threading error in RunMainBoardThread: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
g_Config.multiThreaded = false; m_multiThreaded = false;
return 1; return 1;
} }
@ -2289,7 +2292,7 @@ bool CModel3::WakeSoundBoardThread(void)
ThreadError: ThreadError:
ErrorLog("Threading error in WakeSoundBoardThread: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError()); ErrorLog("Threading error in WakeSoundBoardThread: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
g_Config.multiThreaded = false; m_multiThreaded = false;
return false; return false;
} }
@ -2373,7 +2376,7 @@ int CModel3::RunSoundBoardThread(void)
ThreadError: ThreadError:
ErrorLog("Threading error in RunSoundBoardThread: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError()); ErrorLog("Threading error in RunSoundBoardThread: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
g_Config.multiThreaded = false; m_multiThreaded = false;
return 1; return 1;
} }
@ -2429,7 +2432,7 @@ int CModel3::RunSoundBoardThreadSyncd(void)
ThreadError: ThreadError:
ErrorLog("Threading error in RunSoundBoardThreadSyncd: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError()); ErrorLog("Threading error in RunSoundBoardThreadSyncd: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
g_Config.multiThreaded = false; m_multiThreaded = false;
return 1; return 1;
} }
@ -2485,7 +2488,7 @@ int CModel3::RunDriveBoardThread(void)
ThreadError: ThreadError:
ErrorLog("Threading error in RunDriveBoardThread: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError()); ErrorLog("Threading error in RunDriveBoardThread: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError());
g_Config.multiThreaded = false; m_multiThreaded = false;
return 1; return 1;
} }
@ -2546,13 +2549,13 @@ void CModel3::Reset(void)
******************************************************************************/ ******************************************************************************/
// Apply patches to games // Apply patches to games
void CModel3::Patch(void) static void Patch(uint8_t *crom, const Game &game)
{ {
if (!strcmp(Game->id, "scudp")) if (game.name == "scudp")
{ {
// Base offset of program in CROM: 0x710000 // Base offset of program in CROM: 0x710000
} }
else if (!strcmp(Game->id, "lemans24")) else if (game.name == "lemans24")
{ {
// Base offset of program in CROM: 6473C0 // Base offset of program in CROM: 6473C0
*(UINT32 *) &crom[0x6D8C4C] = 0x00000002; // comm. mode: 00=master, 01=slave, 02=satellite *(UINT32 *) &crom[0x6D8C4C] = 0x00000002; // comm. mode: 00=master, 01=slave, 02=satellite
@ -2561,18 +2564,18 @@ void CModel3::Patch(void)
*(UINT32 *) &crom[0x73EDD0] = 0x60000000; *(UINT32 *) &crom[0x73EDD0] = 0x60000000;
*(UINT32 *) &crom[0x73EDC4] = 0x60000000; *(UINT32 *) &crom[0x73EDC4] = 0x60000000;
} }
else if (!strcmp(Game->id, "lostwsga")) else if (game.name == "lostwsga")
{ {
*(UINT32 *) &crom[0x7374f4] = 0x38840004; // an actual bug in the game code *(UINT32 *) &crom[0x7374f4] = 0x38840004; // an actual bug in the game code
} }
else if (!strcmp(Game->id, "vs215") || !strcmp(Game->id, "vs215o") || !strcmp(Game->id, "vs29815")) else if (game.name == "vs215" || game.name == "vs215o" || game.name == "vs29815")
{ {
// VS215 is a modification of VS2 that runs on Step 1.5 hardware. I // VS215 is a modification of VS2 that runs on Step 1.5 hardware. I
// suspect the code here is trying to detect the system type but am too // suspect the code here is trying to detect the system type but am too
// lazy to figure it out right now. // lazy to figure it out right now.
*(UINT32 *) &crom[0x7001A8] = 0x48000000+(0xFFF01630-0xFFF001A8); // force a jump to FFF01630 *(UINT32 *) &crom[0x7001A8] = 0x48000000+(0xFFF01630-0xFFF001A8); // force a jump to FFF01630
} }
else if (!strcmp(Game->id, "vs298")) else if (game.name == "vs298")
{ {
// Base offset of program in CROM: 600000 // Base offset of program in CROM: 600000
// Inexplicably, at PC=AFC1C, a call is made to FC78, which is right in the middle of some // Inexplicably, at PC=AFC1C, a call is made to FC78, which is right in the middle of some
@ -2581,36 +2584,36 @@ void CModel3::Patch(void)
// Or, 300138 needs to be written with a non-zero value, it is loaded from EEPROM but is 0. // Or, 300138 needs to be written with a non-zero value, it is loaded from EEPROM but is 0.
*(UINT32 *) &crom[0x6AFC1C] = 0x60000000; *(UINT32 *) &crom[0x6AFC1C] = 0x60000000;
} }
else if (!strcmp(Game->id, "srally2")) else if (game.name == "srally2")
{ {
*(UINT32 *) &crom[0x7C0C4] = 0x60000000; *(UINT32 *) &crom[0x7C0C4] = 0x60000000;
*(UINT32 *) &crom[0x7C0C8] = 0x60000000; *(UINT32 *) &crom[0x7C0C8] = 0x60000000;
*(UINT32 *) &crom[0x7C0CC] = 0x60000000; *(UINT32 *) &crom[0x7C0CC] = 0x60000000;
} }
else if (!strcmp(Game->id, "harley")) else if (game.name == "harley")
{ {
*(UINT32 *) &crom[0x50E8D4] = 0x60000000; *(UINT32 *) &crom[0x50E8D4] = 0x60000000;
*(UINT32 *) &crom[0x50E8F4] = 0x60000000; *(UINT32 *) &crom[0x50E8F4] = 0x60000000;
*(UINT32 *) &crom[0x50FB84] = 0x60000000; *(UINT32 *) &crom[0x50FB84] = 0x60000000;
} }
else if (!strcmp(Game->id, "harleyb")) else if (game.name == "harleyb")
{ {
*(UINT32 *) &crom[0x50ECB4] = 0x60000000; *(UINT32 *) &crom[0x50ECB4] = 0x60000000;
*(UINT32 *) &crom[0x50ECD4] = 0x60000000; *(UINT32 *) &crom[0x50ECD4] = 0x60000000;
*(UINT32 *) &crom[0x50FF64] = 0x60000000; *(UINT32 *) &crom[0x50FF64] = 0x60000000;
} }
else if (!strcmp(Game->id, "swtrilgy")) else if (game.name == "swtrilgy")
{ {
*(UINT32 *) &crom[0xF0E48] = 0x60000000; *(UINT32 *) &crom[0xF0E48] = 0x60000000;
*(UINT32 *) &crom[0x043DC] = 0x48000090; // related to joystick feedback *(UINT32 *) &crom[0x043DC] = 0x48000090; // related to joystick feedback
*(UINT32 *) &crom[0x029A0] = 0x60000000; *(UINT32 *) &crom[0x029A0] = 0x60000000;
*(UINT32 *) &crom[0x02A0C] = 0x60000000; *(UINT32 *) &crom[0x02A0C] = 0x60000000;
} }
else if (!strcmp(Game->id, "swtrilgya")) else if (game.name == "swtrilgya")
{ {
*(UINT32 *) &crom[0xF6DD0] = 0x60000000; // from MAME *(UINT32 *) &crom[0xF6DD0] = 0x60000000; // from MAME
} }
else if (!strcmp(Game->id, "eca") || !strcmp(Game->id, "ecax")) else if (game.name == "eca" || game.name == "ecax")
{ {
*(UINT32 *) &crom[0x535580] = 0x60000000; *(UINT32 *) &crom[0x535580] = 0x60000000;
//*(UINT32 *) &crom[0x5023B4] = 0x60000000; //*(UINT32 *) &crom[0x5023B4] = 0x60000000;
@ -2660,89 +2663,98 @@ static void Reverse32(uint8_t *buf, size_t size)
// 64-bit magic number used to detect loading of optional ROMs // 64-bit magic number used to detect loading of optional ROMs
#define MAGIC_NUMBER 0x4C444D5245505553ULL #define MAGIC_NUMBER 0x4C444D5245505553ULL
const struct GameInfo * CModel3::GetGameInfo(void) const Game &CModel3::GetGame() const
{ {
return Game; return m_game;
} }
// Stepping-dependent parameters (MPC10x type, etc.) are initialized here // Stepping-dependent parameters (MPC10x type, etc.) are initialized here
bool CModel3::LoadROMSet(const struct GameInfo *GameList, const char *zipFile) bool CModel3::LoadGame(const Game &game, const ROMSet &rom_set)
{ {
struct ROMMap Map[] = m_game = Game();
/*
* Copy in ROM data with mirroring as necessary for the following cases:
*
* - VROM: 64MB. If <= 32MB, mirror to high 32MB.
* - Banked CROM: 128MB. If <= 64MB, mirror to high 64MB.
* - Fixed CROM: 8MB. If < 8MB, loaded only in high part of space and low
* part is a mirror of (banked) CROM0.
* - Sample ROM: 16MB. If <= 8MB, mirror to high 8MB.
*
* ROMs are released after being loaded.
*/
if (rom_set.get_rom("vrom").size <= 32*0x100000)
{ {
{ "CROM", crom }, rom_set.get_rom("vrom").CopyTo(&vrom[0], 32*100000);
{ "CROMxx", &crom[0x800000] }, rom_set.get_rom("vrom").CopyTo(&vrom[32*0x100000], 32*0x100000);
{ "VROM", vrom },
{ "SndProg", soundROM },
{ "Samples", sampleROM },
{ "DSBProg", dsbROM },
{ "DSBMPEG", mpegROM },
{ "DriveBd", driveROM },
{ NULL, NULL }
};
PPC_CONFIG PPCConfig;
// Magic numbers to detect if optional ROMs are loaded
*(UINT64 *) driveROM = MAGIC_NUMBER;
// Load game
Game = LoadROMSetFromZIPFile(Map, GameList, zipFile, true);
if (NULL == Game)
return ErrorLog("Failed to load ROM set.");
// Perform mirroring as necessary
if (Game->vromSize < 0x4000000) // VROM is actually 64 MB
CopyRegion(vrom, Game->vromSize, 0x4000000, vrom, Game->vromSize);
if (Game->cromSize < 0x800000) // low part of fixed CROM region contains CROM0
CopyRegion(crom, 0, 0x800000-Game->cromSize, &crom[0x800000], 0x800000);
if (Game->mirrorLow64MB) // for games w/ 64 MB or less banked CROM, mirror to upper 128 MB
CopyRegion(&crom[0x800000], 0x4000000, 0x8000000, &crom[0x800000], 0x4000000);
if (Game->sampleSize < 0x1000000) // if less than 16 MB of sample ROMs, mirror
CopyRegion(sampleROM, 0x800000, 0x1000000, sampleROM, 0x800000);
// Byte reverse the PowerPC ROMs (convert to little endian words)
Reverse32(crom, 0x800000+0x8000000);
// Byte swap sound board 68K ROMs (convert to little endian words)
Reverse16(soundROM, 0x80000);
Reverse16(sampleROM, 0x1000000);
// Initialize CPU and configure hardware (CPU speed is set in Init())
if (Game->step >= 0x20) // Step 2.0+
{
PPCConfig.pvr = PPC_MODEL_603R; // 166 MHz
PPCConfig.bus_frequency = BUS_FREQUENCY_66MHZ;
PPCConfig.bus_frequency_multiplier = 0x25; // 2.5X multiplier
PCIBridge.SetModel(0x106); // MPC106
}
else if (Game->step == 0x15) // Step 1.5
{
PPCConfig.pvr = PPC_MODEL_603E; // 100 MHz
PPCConfig.bus_frequency = BUS_FREQUENCY_66MHZ;
PPCConfig.bus_frequency_multiplier = 0x15; // 1.5X multiplier
if (!strcmp(Game->id, "scudp1")) // some Step 1.x games use MPC106
PCIBridge.SetModel(0x106);
else
PCIBridge.SetModel(0x105); // MPC105
}
else if (Game->step == 0x10) // Step 1.0
{
PPCConfig.pvr = PPC_MODEL_603R; // 66 MHz
PPCConfig.bus_frequency = BUS_FREQUENCY_66MHZ;
PPCConfig.bus_frequency_multiplier = 0x10; // 1X multiplier
if (!strcmp(Game->id, "bass") || !strcmp(Game->id, "getbass")) // some Step 1.x games use MPC106
PCIBridge.SetModel(0x106);
else
PCIBridge.SetModel(0x105); // MPC105
} }
else else
return ErrorLog("Game uses an unrecognized stepping (%d.%d), cannot configure Model 3.", (Game->step>>4)&0xF, Game->step&0xF); rom_set.get_rom("vrom").CopyTo(vrom, 64*0x100000);
if (rom_set.get_rom("banked_crom").size <= 64*0x100000)
{
rom_set.get_rom("banked_crom").CopyTo(&crom[8*0x100000 + 0], 64*0x100000);
rom_set.get_rom("banked_crom").CopyTo(&crom[8*0x100000 + 64*0x100000], 64*0x100000);
}
else
rom_set.get_rom("banked_crom").CopyTo(&crom[8*0x100000 + 0], 128*0x100000);
size_t crom_size = rom_set.get_rom("crom").size;
rom_set.get_rom("crom").CopyTo(&crom[8*0x100000 - crom_size], crom_size);
if (crom_size < 8*0x100000)
rom_set.get_rom("banked_crom").CopyTo(&crom[0], 8*0x100000 - crom_size);
if (rom_set.get_rom("sound_samples").size <= 8*0x100000)
{
rom_set.get_rom("sound_samples").CopyTo(&sampleROM[0], 8*0x100000);
rom_set.get_rom("sound_samples").CopyTo(&sampleROM[8*0x100000], 8*0x100000);
}
else
rom_set.get_rom("sound_samples").CopyTo(sampleROM, 16*0x100000);
rom_set.get_rom("sound_program").CopyTo(soundROM, 512*1024);
rom_set.get_rom("mpeg_program").CopyTo(dsbROM, 128*1024);
rom_set.get_rom("mpeg_music").CopyTo(mpegROM, 16*0x100000);
rom_set.get_rom("driveboard_program").CopyTo(driveROM, 64*1024);
// Convert PowerPC and 68K ROMs to little endian words
Util::FlipEndian32(crom, 8*0x100000 + 128*0x100000);
Util::FlipEndian16(soundROM, 512*1024);
Util::FlipEndian16(sampleROM, 16*0x100000);
GPU.SetStep(Game->step); // Initialize CPU
PPC_CONFIG ppc_config;
ppc_init(&PPCConfig); if (game.stepping == "2.0" || game.stepping == "2.1")
{
ppc_config.pvr = PPC_MODEL_603R; // 166 MHz
ppc_config.bus_frequency = BUS_FREQUENCY_66MHZ;
ppc_config.bus_frequency_multiplier = 0x25; // 2.5X multiplier
PCIBridge.SetModel(0x106); // MPC106
}
else if (game.stepping == "1.5")
{
ppc_config.pvr = PPC_MODEL_603E; // 100 MHz
ppc_config.bus_frequency = BUS_FREQUENCY_66MHZ;
ppc_config.bus_frequency_multiplier = 0x15; // 1.5X multiplier
if (game.name == "scudp1")
PCIBridge.SetModel(0x106); // some Step 1.x games use MPC106
else
PCIBridge.SetModel(0x105); // MPC105
}
else if (game.stepping == "1.0")
{
ppc_config.pvr = PPC_MODEL_603R; // 66 MHz
ppc_config.bus_frequency = BUS_FREQUENCY_66MHZ;
ppc_config.bus_frequency_multiplier = 0x10; // 1X multiplier
if (game.name == "bass" || game.name == "getbass")
PCIBridge.SetModel(0x106); // some Step 1.x games use MPC106
else
PCIBridge.SetModel(0x105); // MPC105
}
else
{
ErrorLog("Cannot configure Model 3 because game uses unrecognized stepping (%s).", game.stepping.c_str());
return FAIL;
}
ppc_init(&ppc_config);
ppc_attach_bus(this); ppc_attach_bus(this);
PPCFetchRegions[0].start = 0; PPCFetchRegions[0].start = 0;
PPCFetchRegions[0].end = 0x007FFFFF; PPCFetchRegions[0].end = 0x007FFFFF;
PPCFetchRegions[0].ptr = (UINT32 *) ram; PPCFetchRegions[0].ptr = (UINT32 *) ram;
@ -2752,67 +2764,71 @@ bool CModel3::LoadROMSet(const struct GameInfo *GameList, const char *zipFile)
PPCFetchRegions[2].start = 0; PPCFetchRegions[2].start = 0;
PPCFetchRegions[2].end = 0; PPCFetchRegions[2].end = 0;
PPCFetchRegions[2].ptr = NULL; PPCFetchRegions[2].ptr = NULL;
ppc_set_fetch(PPCFetchRegions); ppc_set_fetch(PPCFetchRegions);
// DSB board (if present) // Initialize Real3D
if (Game->mpegBoard == 1) // Z80 board, do not byte swap program ROM int stepping = ((game.stepping[0] - '0') << 4) | (game.stepping[2] - '0');
GPU.SetStepping(stepping);
// MPEG board (if present)
if (rom_set.get_rom("mpeg_program").size)
{ {
DSB = new(std::nothrow) CDSB1(); if (game.mpeg_board == "DSB1")
if (NULL == DSB) {
return ErrorLog("Insufficient memory for Digital Sound Board object."); DSB = new(std::nothrow) CDSB1(m_config);
if (OKAY != DSB->Init(dsbROM,mpegROM)) if (NULL == DSB)
return FAIL; return ErrorLog("Insufficient memory for Digital Sound Board object.");
} }
else if (Game->mpegBoard == 2) // 68K board else if (game.mpeg_board == "DSB2")
{ {
Reverse16(dsbROM, 0x20000); // byte swap program ROM Util::FlipEndian16(dsbROM, 128*1024); // 68K program needs to be byte swapped
DSB = new(std::nothrow) CDSB2(); DSB = new(std::nothrow) CDSB2(m_config);
if (NULL == DSB) if (NULL == DSB)
return ErrorLog("Insufficient memory for Digital Sound Board object."); return ErrorLog("Insufficient memory for Digital Sound Board object.");
if (OKAY != DSB->Init(dsbROM,mpegROM)) }
else if (game.mpeg_board.empty())
ErrorLog("No MPEG board type defined in game XML for MPEG ROMs.");
else
ErrorLog("Unknown MPEG board type '%s'. Only 'DSB1' and 'DSB2' are supported.", game.mpeg_board.c_str());
if (DSB && OKAY != DSB->Init(dsbROM, mpegROM))
return FAIL; return FAIL;
} }
SoundBoard.AttachDSB(DSB); SoundBoard.AttachDSB(DSB);
// Drive board (if present) // Drive board (if present)
if (Game->driveBoard) if (rom_set.get_rom("driveboard_program").size)
{ {
// Was the optional drive board ROM loaded? if (DriveBoard.Init(driveROM))
if (MAGIC_NUMBER != *(UINT64 *) driveROM) // magic number overwritten by ROM return FAIL;
{
if (DriveBoard.Init(driveROM))
return FAIL;
}
else
DriveBoard.Init(NULL);
} }
else else
DriveBoard.Init(NULL); // disable DriveBoard.Init(NULL);
// Security board encryption device // Security board encryption device
m_cryptoDevice.Init(Game->encryptionKey, std::bind(&CModel3::ReadSecurityRAM, this, std::placeholders::_1)); m_cryptoDevice.Init(game.encryption_key, std::bind(&CModel3::ReadSecurityRAM, this, std::placeholders::_1));
// Apply ROM patches // Apply ROM patches
Patch(); //TODO: place these in XML
Patch(crom, game);
// Print game information // Print game information
std::set<std::string> extraHw; std::set<std::string> extra_hw;
if (Game->mpegBoard) if (DSB)
extraHw.insert(Util::Format() << "Digital Sound Board (Type " << Game->mpegBoard << ")"); extra_hw.insert(Util::Format() << "Digital Sound Board (Type " << game.mpeg_board << ")");
if (Game->driveBoard) if (rom_set.get_rom("driveboard_program").size)
extraHw.insert("Drive Board"); extra_hw.insert("Drive Board");
if (Game->encryptionKey) if (game.encryption_key)
extraHw.insert("Security Board"); extra_hw.insert("Security Board");
printf(" Title: %s\n", Game->title); std::cout << " Title: " << game.title << std::endl;
printf(" ROM Set: %s\n", Game->id); std::cout << " ROM Set: " << game.name << std::endl;
printf(" Developer: %s\n", Game->mfgName); std::cout << " Developer: " << game.manufacturer << std::endl;
printf(" Year: %d\n", Game->year); std::cout << " Year: " << game.year << std::endl;
printf(" Step: %d.%d\n", (Game->step>>4)&0xF, Game->step&0xF); std::cout << " Stepping: " << game.stepping << std::endl;
if (!extraHw.empty()) if (!extra_hw.empty())
printf(" Extra Hardware: %s\n", Util::Format(", ").Join(extraHw).str().c_str()); std::cout << " Extra Hardware: " << Util::Format(", ").Join(extra_hw) << std::endl;
printf("\n"); std::cout << std::endl;
m_game = game;
return OKAY; return OKAY;
} }
@ -2827,7 +2843,7 @@ void CModel3::AttachInputs(CInputs *InputsPtr)
Inputs = InputsPtr; Inputs = InputsPtr;
if (DriveBoard.IsAttached()) if (DriveBoard.IsAttached())
DriveBoard.AttachInputs(Inputs, Game->inputFlags); DriveBoard.AttachInputs(Inputs, m_game.inputs);
DebugLog("Model 3 attached inputs\n"); DebugLog("Model 3 attached inputs\n");
} }
@ -2835,7 +2851,7 @@ void CModel3::AttachInputs(CInputs *InputsPtr)
void CModel3::AttachOutputs(COutputs *OutputsPtr) void CModel3::AttachOutputs(COutputs *OutputsPtr)
{ {
Outputs = OutputsPtr; Outputs = OutputsPtr;
Outputs->SetGame(Game); Outputs->SetGame(m_game);
Outputs->Attached(); Outputs->Attached();
if (DriveBoard.IsAttached()) if (DriveBoard.IsAttached())
@ -2853,6 +2869,7 @@ bool CModel3::Init(void)
memoryPool = new(std::nothrow) UINT8[MEMORY_POOL_SIZE]; memoryPool = new(std::nothrow) UINT8[MEMORY_POOL_SIZE];
if (NULL == memoryPool) if (NULL == memoryPool)
return ErrorLog("Insufficient memory for Model 3 object (needs %1.1f MB).", memSizeMB); return ErrorLog("Insufficient memory for Model 3 object (needs %1.1f MB).", memSizeMB);
memset(memoryPool, 0, MEMORY_POOL_SIZE);
// Set up pointers // Set up pointers
ram = &memoryPool[OFFSET_RAM]; ram = &memoryPool[OFFSET_RAM];
@ -2901,13 +2918,19 @@ CDriveBoard *CModel3::GetDriveBoard(void)
return &DriveBoard; return &DriveBoard;
} }
CModel3::CModel3(void) CModel3::CModel3(const Util::Config::Node &config)
: m_config(config),
m_multiThreaded(config["MultiThreaded"].ValueAs<bool>()),
m_gpuMultiThreaded(config["GPUMultiThreaded"].ValueAs<bool>()),
TileGen(config),
GPU(config),
SoundBoard(config),
DriveBoard(config)
{ {
// Initialize pointers so dtor can know whether to free them // Initialize pointers so dtor can know whether to free them
memoryPool = NULL; memoryPool = NULL;
// Various uninitialized pointers // Various uninitialized pointers
Game = NULL;
Inputs = NULL; Inputs = NULL;
Outputs = NULL; Outputs = NULL;
ram = NULL; ram = NULL;
@ -2995,7 +3018,6 @@ CModel3::~CModel3(void)
DSB = NULL; DSB = NULL;
} }
Game = NULL;
Inputs = NULL; Inputs = NULL;
Outputs = NULL; Outputs = NULL;
ram = NULL; ram = NULL;

View file

@ -30,6 +30,7 @@
#include "Model3/IEmulator.h" #include "Model3/IEmulator.h"
#include "Model3/Crypto.h" #include "Model3/Crypto.h"
#include "Util/NewConfig.h"
/* /*
* FrameTimings * FrameTimings
@ -47,44 +48,6 @@ struct FrameTimings
UINT32 frameTicks; UINT32 frameTicks;
}; };
/*
* CModel3Config:
*
* Settings used by CModel3.
*/
class CModel3Config
{
public:
bool multiThreaded; // Multi-threaded (enabled if true)
bool gpuMultiThreaded; // Multi-threaded rendering (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 50 MHz.");
f = 50;
}
ppcFrequency = f*1000000;
}
inline unsigned GetPowerPCFrequency(void)
{
return ppcFrequency/1000000;
}
// Defaults
CModel3Config(void)
{
multiThreaded = true; // enable by default
gpuMultiThreaded = true; // enable by default
ppcFrequency = 50*1000000; // 50 MHz
}
private:
unsigned ppcFrequency; // in Hz
};
/* /*
* CModel3: * CModel3:
* *
@ -110,7 +73,7 @@ public:
void RunFrame(void); void RunFrame(void);
void RenderFrame(void); void RenderFrame(void);
void Reset(void); void Reset(void);
const struct GameInfo * GetGameInfo(void); const Game &GetGame(void) const;
void AttachRenderers(CRender2D *Render2DPtr, IRender3D *Render3DPtr); void AttachRenderers(CRender2D *Render2DPtr, IRender3D *Render3DPtr);
void AttachInputs(CInputs *InputsPtr); void AttachInputs(CInputs *InputsPtr);
void AttachOutputs(COutputs *OutputsPtr); void AttachOutputs(COutputs *OutputsPtr);
@ -131,20 +94,19 @@ public:
void Write64(UINT32 addr, UINT64 data); void Write64(UINT32 addr, UINT64 data);
/* /*
* LoadROMSet(GameList, zipFile): * LoadGame(game, rom_set):
* *
* Loads a complete ROM set from the specified ZIP archive. * Loads a game, copying in the provided ROMs and setting the hardware
* * stepping.
* NOTE: Command line settings will not have been applied here yet.
* *
* Parameters: * Parameters:
* GameList List of all supported games and their ROMs. * game Game information.
* zipFile ZIP file to load from. * rom_set ROMs.
* *
* Returns: * Returns:
* OKAY if successful, FAIL otherwise. Prints errors. * OKAY if successful, FAIL otherwise. Prints errors.
*/ */
bool LoadROMSet(const struct GameInfo *GameList, const char *zipFile); bool LoadGame(const Game &game, const ROMSet &rom_set);
/* /*
* GetSoundBoard(void): * GetSoundBoard(void):
@ -181,15 +143,19 @@ public:
FrameTimings GetTimings(void); FrameTimings GetTimings(void);
/* /*
* CModel3(void): * CModel3(config):
* ~CModel3(void): * ~CModel3(void):
* *
* Constructor and destructor for Model 3 class. Constructor performs a * Constructor and destructor for Model 3 class. Constructor performs a
* bare-bones initialization of object; does not perform any memory * bare-bones initialization of object; does not perform any memory
* allocation or any actions that can fail. The destructor will deallocate * allocation or any actions that can fail. The destructor will deallocate
* memory and free resources used by the object (and its child objects). * memory and free resources used by the object (and its child objects).
*
* Paramters:
* config Run-time configuration. The reference should be held because
* this changes at run-time.
*/ */
CModel3(void); CModel3(const Util::Config::Node &config);
~CModel3(void); ~CModel3(void);
/* /*
@ -206,7 +172,6 @@ private:
void SetCROMBank(unsigned idx); void SetCROMBank(unsigned idx);
UINT8 ReadSystemRegister(unsigned reg); UINT8 ReadSystemRegister(unsigned reg);
void WriteSystemRegister(unsigned reg, UINT8 data); void WriteSystemRegister(unsigned reg, UINT8 data);
void Patch(void);
void RunMainBoardFrame(void); // Runs PPC main board for a frame void RunMainBoardFrame(void); // Runs PPC main board for a frame
void SyncGPUs(void); // Sync's up GPUs in preparation for rendering - must be called when PPC is not running void SyncGPUs(void); // Sync's up GPUs in preparation for rendering - must be called when PPC is not running
@ -230,8 +195,13 @@ private:
int RunSoundBoardThreadSyncd(void); // Runs sound board thread (sync'd in step with render thread) int RunSoundBoardThreadSyncd(void); // Runs sound board thread (sync'd in step with render thread)
int RunDriveBoardThread(void); // Runs drive board thread (sync'd in step with render thread) int RunDriveBoardThread(void); // Runs drive board thread (sync'd in step with render thread)
// Runtime configuration
const Util::Config::Node &m_config;
bool m_multiThreaded;
bool m_gpuMultiThreaded;
// Game and hardware information // Game and hardware information
const struct GameInfo *Game; Game m_game;
// Game inputs and outputs // Game inputs and outputs
CInputs *Inputs; CInputs *Inputs;

View file

@ -90,11 +90,18 @@ public:
} }
} }
const struct GameInfo * GetGameInfo(void) const Game &GetGame(void)
{ {
return m_game; return m_game;
} }
bool LoadGame(const Game &game)
{
//TODO: write me
return FAIL;
}
//TODO: replicate this logic in LoadGame()
bool LoadROMSet(const struct GameInfo *gameList, const char *zipFile) bool LoadROMSet(const struct GameInfo *gameList, const char *zipFile)
{ {
// Load ROM // Load ROM

View file

@ -111,7 +111,7 @@ void CReal3D::LoadState(CBlockFile *SaveState)
SaveState->Read(memoryPool, MEM_POOL_SIZE_RW); SaveState->Read(memoryPool, MEM_POOL_SIZE_RW);
// If multi-threaded, update read-only snapshots too // If multi-threaded, update read-only snapshots too
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
UpdateSnapshots(true); UpdateSnapshots(true);
Render3D->UploadTextures(0, 0, 0, 2048, 2048); Render3D->UploadTextures(0, 0, 0, 2048, 2048);
SaveState->Read(&fifoIdx, sizeof(fifoIdx)); SaveState->Read(&fifoIdx, sizeof(fifoIdx));
@ -159,7 +159,7 @@ uint32_t CReal3D::SyncSnapshots(void)
commandPortWrittenRO = commandPortWritten; commandPortWrittenRO = commandPortWritten;
commandPortWritten = false; commandPortWritten = false;
if (!g_Config.gpuMultiThreaded) if (!m_gpuMultiThreaded)
return 0; return 0;
// Update read-only queue // Update read-only queue
@ -230,7 +230,7 @@ uint32_t CReal3D::UpdateSnapshots(bool copyWhole)
void CReal3D::BeginFrame(void) void CReal3D::BeginFrame(void)
{ {
// If multi-threaded, perform now any queued texture uploads to renderer before rendering begins // If multi-threaded, perform now any queued texture uploads to renderer before rendering begins
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
{ {
for (const auto &it : queuedUploadTexturesRO) { for (const auto &it : queuedUploadTexturesRO) {
Render3D->UploadTextures(it.level, it.x, it.y, it.width, it.height); Render3D->UploadTextures(it.level, it.x, it.y, it.width, it.height);
@ -632,7 +632,7 @@ void CReal3D::StoreTexture(unsigned level, unsigned xPos, unsigned yPos, unsigne
{ {
for (uint32_t xx = 0; xx < 8; xx++) for (uint32_t xx = 0; xx < 8; xx++)
{ {
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
MARK_DIRTY(textureRAMDirty, destOffset * 2); MARK_DIRTY(textureRAMDirty, destOffset * 2);
textureRAM[destOffset++] = texData[decode[(yy*8+xx)^1]]; textureRAM[destOffset++] = texData[decode[(yy*8+xx)^1]];
} }
@ -668,11 +668,11 @@ void CReal3D::StoreTexture(unsigned level, unsigned xPos, unsigned yPos, unsigne
{ {
uint8_t byte1 = texData[decode[(yy^1)*8+((xx+0)^1)]/2]>>8; uint8_t byte1 = texData[decode[(yy^1)*8+((xx+0)^1)]/2]>>8;
uint8_t byte2 = texData[decode[(yy^1)*8+((xx+1)^1)]/2]&0xFF; uint8_t byte2 = texData[decode[(yy^1)*8+((xx+1)^1)]/2]&0xFF;
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
MARK_DIRTY(textureRAMDirty, destOffset * 2); MARK_DIRTY(textureRAMDirty, destOffset * 2);
StoreTexelByte(&textureRAM[destOffset], byteSelect, byte1); StoreTexelByte(&textureRAM[destOffset], byteSelect, byte1);
++destOffset; ++destOffset;
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
MARK_DIRTY(textureRAMDirty, destOffset * 2); MARK_DIRTY(textureRAMDirty, destOffset * 2);
StoreTexelByte(&textureRAM[destOffset], byteSelect, byte2); StoreTexelByte(&textureRAM[destOffset], byteSelect, byte2);
++destOffset; ++destOffset;
@ -686,7 +686,7 @@ void CReal3D::StoreTexture(unsigned level, unsigned xPos, unsigned yPos, unsigne
// Signal to renderer that textures have changed // Signal to renderer that textures have changed
// TO-DO: mipmaps? What if a game writes non-mipmap textures to mipmap area? // TO-DO: mipmaps? What if a game writes non-mipmap textures to mipmap area?
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
{ {
// If multi-threaded, then queue calls to UploadTextures for render thread to perform at beginning of next frame // If multi-threaded, then queue calls to UploadTextures for render thread to perform at beginning of next frame
QueuedUploadTextures upl; QueuedUploadTextures upl;
@ -866,21 +866,21 @@ void CReal3D::WriteTexturePort(unsigned reg, uint32_t data)
void CReal3D::WriteLowCullingRAM(uint32_t addr, uint32_t data) void CReal3D::WriteLowCullingRAM(uint32_t addr, uint32_t data)
{ {
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
MARK_DIRTY(cullingRAMLoDirty, addr); MARK_DIRTY(cullingRAMLoDirty, addr);
cullingRAMLo[addr/4] = data; cullingRAMLo[addr/4] = data;
} }
void CReal3D::WriteHighCullingRAM(uint32_t addr, uint32_t data) void CReal3D::WriteHighCullingRAM(uint32_t addr, uint32_t data)
{ {
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
MARK_DIRTY(cullingRAMHiDirty, addr); MARK_DIRTY(cullingRAMHiDirty, addr);
cullingRAMHi[addr/4] = data; cullingRAMHi[addr/4] = data;
} }
void CReal3D::WritePolygonRAM(uint32_t addr, uint32_t data) void CReal3D::WritePolygonRAM(uint32_t addr, uint32_t data)
{ {
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
MARK_DIRTY(polyRAMDirty, addr); MARK_DIRTY(polyRAMDirty, addr);
polyRAM[addr/4] = data; polyRAM[addr/4] = data;
} }
@ -958,7 +958,7 @@ void CReal3D::Reset(void)
dmaStatus = 0; dmaStatus = 0;
dmaUnknownReg = 0; dmaUnknownReg = 0;
unsigned memSize = (g_Config.gpuMultiThreaded ? MEMORY_POOL_SIZE : MEM_POOL_SIZE_RW); unsigned memSize = (m_gpuMultiThreaded ? MEMORY_POOL_SIZE : MEM_POOL_SIZE_RW);
memset(memoryPool, 0, memSize); memset(memoryPool, 0, memSize);
memset(m_vromTextureFIFO, 0, sizeof(m_vromTextureFIFO)); memset(m_vromTextureFIFO, 0, sizeof(m_vromTextureFIFO));
@ -974,20 +974,20 @@ void CReal3D::AttachRenderer(IRender3D *Render3DPtr)
{ {
Render3D = Render3DPtr; Render3D = Render3DPtr;
// If multi-threaded, attach read-only snapshots to renderer instead of real ones // If mult-threaded, attach read-only snapshots to renderer instead of real ones
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
Render3D->AttachMemory(cullingRAMLoRO, cullingRAMHiRO, polyRAMRO, vrom, textureRAMRO); Render3D->AttachMemory(cullingRAMLoRO, cullingRAMHiRO, polyRAMRO, vrom, textureRAMRO);
else else
Render3D->AttachMemory(cullingRAMLo, cullingRAMHi, polyRAM, vrom, textureRAM); Render3D->AttachMemory(cullingRAMLo, cullingRAMHi, polyRAM, vrom, textureRAM);
Render3D->SetStep(step); Render3D->SetStepping(step);
DebugLog("Real3D attached a Render3D object\n"); DebugLog("Real3D attached a Render3D object\n");
} }
void CReal3D::SetStep(int stepID) void CReal3D::SetStepping(int stepping)
{ {
step = stepID; step = stepping;
if ((step!=0x10) && (step!=0x15) && (step!=0x20) && (step!=0x21)) if ((step!=0x10) && (step!=0x15) && (step!=0x20) && (step!=0x21))
{ {
DebugLog("Real3D: Unrecognized stepping: %d.%d\n", (step>>4)&0xF, step&0xF); DebugLog("Real3D: Unrecognized stepping: %d.%d\n", (step>>4)&0xF, step&0xF);
@ -1002,14 +1002,14 @@ void CReal3D::SetStep(int stepID)
// Pass to renderer // Pass to renderer
if (Render3D != NULL) if (Render3D != NULL)
Render3D->SetStep(step); Render3D->SetStepping(step);
DebugLog("Real3D set to Step %d.%d\n", (step>>4)&0xF, step&0xF); DebugLog("Real3D set to Step %d.%d\n", (step>>4)&0xF, step&0xF);
} }
bool CReal3D::Init(const uint8_t *vromPtr, IBus *BusObjectPtr, CIRQ *IRQObjectPtr, unsigned dmaIRQBit) bool CReal3D::Init(const uint8_t *vromPtr, IBus *BusObjectPtr, CIRQ *IRQObjectPtr, unsigned dmaIRQBit)
{ {
uint32_t memSize = (g_Config.gpuMultiThreaded ? MEMORY_POOL_SIZE : MEM_POOL_SIZE_RW); uint32_t memSize = (m_config["GPUMultiThreaded"].ValueAs<bool>() ? MEMORY_POOL_SIZE : MEM_POOL_SIZE_RW);
float memSizeMB = (float)memSize/(float)0x100000; float memSizeMB = (float)memSize/(float)0x100000;
// IRQ and bus objects // IRQ and bus objects
@ -1030,7 +1030,7 @@ bool CReal3D::Init(const uint8_t *vromPtr, IBus *BusObjectPtr, CIRQ *IRQObjectPt
textureFIFO = (uint32_t *) &memoryPool[OFFSET_TEXFIFO]; textureFIFO = (uint32_t *) &memoryPool[OFFSET_TEXFIFO];
// If multi-threaded, set up pointers for read-only snapshots and dirty page arrays too // If multi-threaded, set up pointers for read-only snapshots and dirty page arrays too
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
{ {
cullingRAMLoRO = (uint32_t *) &memoryPool[OFFSET_8C_RO]; cullingRAMLoRO = (uint32_t *) &memoryPool[OFFSET_8C_RO];
cullingRAMHiRO = (uint32_t *) &memoryPool[OFFSET_8E_RO]; cullingRAMHiRO = (uint32_t *) &memoryPool[OFFSET_8E_RO];
@ -1049,7 +1049,9 @@ bool CReal3D::Init(const uint8_t *vromPtr, IBus *BusObjectPtr, CIRQ *IRQObjectPt
return OKAY; return OKAY;
} }
CReal3D::CReal3D(void) CReal3D::CReal3D(const Util::Config::Node &config)
: m_config(config),
m_gpuMultiThreaded(config["GPUMultiThreaded"].ValueAs<bool>())
{ {
Render3D = NULL; Render3D = NULL;
memoryPool = NULL; memoryPool = NULL;
@ -1117,6 +1119,7 @@ CReal3D::~CReal3D(void)
printf("unable to dump %s\n", "texram"); printf("unable to dump %s\n", "texram");
Util::WriteSurfaceToBMP<Util::A1RGB5>("textures.bmp", reinterpret_cast<uint8_t *>(textureRAM), 2048, 2048, false); Util::WriteSurfaceToBMP<Util::A1RGB5>("textures.bmp", reinterpret_cast<uint8_t *>(textureRAM), 2048, 2048, false);
#endif #endif
Util::WriteSurfaceToBMP<Util::A1RGB5>("textures.bmp", reinterpret_cast<uint8_t *>(textureRAM), 2048, 2048, false);
Render3D = NULL; Render3D = NULL;
if (memoryPool != NULL) if (memoryPool != NULL)

View file

@ -334,17 +334,17 @@ public:
void AttachRenderer(IRender3D *Render3DPtr); void AttachRenderer(IRender3D *Render3DPtr);
/* /*
* SetStep(stepID): * SetStepping(stepping):
* *
* Sets the Model 3 hardware stepping, which also determines the Real3D * Sets the Model 3 hardware stepping, which also determines the Real3D
* functionality. The default is Step 1.0. This should be called prior to * functionality. The default is Step 1.0. This should be called prior to
* any other emulation functions and after Init(). * any other emulation functions and after Init().
* *
* Parameters: * Parameters:
* stepID 0x10 for Step 1.0, 0x15 for Step 1.5, 0x20 for Step 2.0, * stepping 0x10 for Step 1.0, 0x15 for Step 1.5, 0x20 for Step 2.0, or
* or 0x21 for Step 2.1. Anything else defaults to 1.0. * 0x21 for Step 2.1. Anything else defaults to 1.0.
*/ */
void SetStep(int stepID); void SetStepping(int stepping);
/* /*
* Init(vromPtr, BusObjectPtr, IRQObjectPtr, dmaIRQBit): * Init(vromPtr, BusObjectPtr, IRQObjectPtr, dmaIRQBit):
@ -370,12 +370,16 @@ public:
bool Init(const uint8_t *vromPtr, IBus *BusObjectPtr, CIRQ *IRQObjectPtr, unsigned dmaIRQBit); bool Init(const uint8_t *vromPtr, IBus *BusObjectPtr, CIRQ *IRQObjectPtr, unsigned dmaIRQBit);
/* /*
* CReal3D(void): * CReal3D(config):
* ~CReal3D(void): * ~CReal3D(void):
* *
* Constructor and destructor. * Constructor and destructor.
*
* Paramters:
* config Run-time configuration. The reference should be held because
* this changes at run-time.
*/ */
CReal3D(void); CReal3D(const Util::Config::Node &config);
~CReal3D(void); ~CReal3D(void);
private: private:
@ -389,6 +393,10 @@ private:
uint32_t UpdateSnapshots(bool copyWhole); uint32_t UpdateSnapshots(bool copyWhole);
uint32_t UpdateSnapshot(bool copyWhole, uint8_t *src, uint8_t *dst, unsigned size, uint8_t *dirty); uint32_t UpdateSnapshot(bool copyWhole, uint8_t *src, uint8_t *dst, unsigned size, uint8_t *dirty);
// Config
const Util::Config::Node &m_config;
const bool m_gpuMultiThreaded;
// Renderer attached to the Real3D // Renderer attached to the Real3D
IRender3D *Render3D; IRender3D *Render3D;

View file

@ -338,7 +338,7 @@ void CSoundBoard::WriteMIDIPort(UINT8 data)
bool CSoundBoard::RunFrame(void) bool CSoundBoard::RunFrame(void)
{ {
// Run sound board first to generate SCSP audio // Run sound board first to generate SCSP audio
if (g_Config.emulateSound) if (m_config["EmulateSound"].ValueAs<bool>())
{ {
M68KSetContext(&M68K); M68KSetContext(&M68K);
SCSP_Update(); SCSP_Update();
@ -355,7 +355,7 @@ bool CSoundBoard::RunFrame(void)
DSB->RunFrame(audioL, audioR); DSB->RunFrame(audioL, audioR);
// Output the audio buffers // Output the audio buffers
bool bufferFull = OutputAudio(44100/60, audioL, audioR); bool bufferFull = OutputAudio(44100/60, audioL, audioR, m_config["FlipStereo"].ValueAs<bool>());
#ifdef SUPERMODEL_LOG_AUDIO #ifdef SUPERMODEL_LOG_AUDIO
// Output to binary file // Output to binary file
@ -478,7 +478,7 @@ bool CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr)
// Initialize SCSPs // Initialize SCSPs
SCSP_SetBuffers(audioL, audioR, 44100/60); SCSP_SetBuffers(audioL, audioR, 44100/60);
SCSP_SetCB(SCSP68KRunCallback, SCSP68KIRQCallback); SCSP_SetCB(SCSP68KRunCallback, SCSP68KIRQCallback);
if (OKAY != SCSP_Init(2)) if (OKAY != SCSP_Init(m_config, 2))
return FAIL; return FAIL;
SCSP_SetRAM(0, ram1); SCSP_SetRAM(0, ram1);
SCSP_SetRAM(1, ram2); SCSP_SetRAM(1, ram2);
@ -503,7 +503,8 @@ CDSB *CSoundBoard::GetDSB(void)
return DSB; return DSB;
} }
CSoundBoard::CSoundBoard(void) CSoundBoard::CSoundBoard(const Util::Config::Node &config)
: m_config(config)
{ {
DSB = NULL; DSB = NULL;
memoryPool = NULL; memoryPool = NULL;

View file

@ -33,50 +33,6 @@
#include "Model3/DSB.h" #include "Model3/DSB.h"
#include "OSD/Thread.h" #include "OSD/Thread.h"
/*
* CSoundBoardConfig:
*
* Settings used by CSoundBoard.
*/
class CSoundBoardConfig
{
public:
bool emulateSound; // sound board emulation (enabled if true)
// Master/slave SCSP relative balance (-100-100, with 100 meaning master volume doubled, slave silenced)
inline void SetSCSPBalance(int bal)
{
if (bal > 100)
{
ErrorLog("Front/rear balance cannot exceed 100%%; setting to 100%%.\n");
bal = 100;
}
if (bal < -100)
{
ErrorLog("Front/rear balance cannot be less than -100%%; setting to -100%%.\n");
bal = -100;
}
scspBalance = bal;
}
inline int GetSCSPBalance(void)
{
return scspBalance;
}
// Defaults
CSoundBoardConfig(void)
{
emulateSound = true;
scspBalance = 0;
}
private:
int scspBalance;
};
/* /*
* CSoundBoard: * CSoundBoard:
* *
@ -211,18 +167,25 @@ public:
bool Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr); bool Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr);
/* /*
* CSoundBoard(void): * CSoundBoard(config):
* ~CSoundBoard(void): * ~CSoundBoard(void):
* *
* Constructor and destructor. * Constructor and destructor.
*
* Paramters:
* config Run-time configuration. The reference should be held because
* this changes at run-time.
*/ */
CSoundBoard(void); CSoundBoard(const Util::Config::Node &config);
~CSoundBoard(void); ~CSoundBoard(void);
private: private:
// Private helper functions // Private helper functions
void UpdateROMBanks(void); void UpdateROMBanks(void);
// Config
const Util::Config::Node &m_config;
// Digital Sound Board // Digital Sound Board
CDSB *DSB; CDSB *DSB;

View file

@ -111,7 +111,7 @@ void CTileGen::LoadState(CBlockFile *SaveState)
RecomputePalettes(); RecomputePalettes();
// If multi-threaded, update read-only snapshots too // If multi-threaded, update read-only snapshots too
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
UpdateSnapshots(true); UpdateSnapshots(true);
} }
@ -144,7 +144,7 @@ void CTileGen::EndVBlank(void)
void CTileGen::RecomputePalettes(void) void CTileGen::RecomputePalettes(void)
{ {
// Writing the colors forces palettes to be computed // Writing the colors forces palettes to be computed
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
{ {
for (unsigned colorAddr = 0; colorAddr < 32768*4; colorAddr += 4 ) for (unsigned colorAddr = 0; colorAddr < 32768*4; colorAddr += 4 )
{ {
@ -169,7 +169,7 @@ UINT32 CTileGen::SyncSnapshots(void)
recomputePalettes = false; recomputePalettes = false;
} }
if (!g_Config.gpuMultiThreaded) if (!m_gpuMultiThreaded)
return 0; return 0;
// Update read-only snapshots // Update read-only snapshots
@ -274,7 +274,7 @@ UINT32 CTileGen::ReadRAM32(unsigned addr)
void CTileGen::WriteRAM32(unsigned addr, UINT32 data) void CTileGen::WriteRAM32(unsigned addr, UINT32 data)
{ {
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
MARK_DIRTY(vramDirty, addr); MARK_DIRTY(vramDirty, addr);
*(UINT32 *) &vram[addr] = data; *(UINT32 *) &vram[addr] = data;
@ -285,7 +285,7 @@ void CTileGen::WriteRAM32(unsigned addr, UINT32 data)
unsigned color = addr/4; // color index unsigned color = addr/4; // color index
// Same address in both palettes must be marked dirty // Same address in both palettes must be marked dirty
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
{ {
MARK_DIRTY(palDirty[0], addr); MARK_DIRTY(palDirty[0], addr);
MARK_DIRTY(palDirty[1], addr); MARK_DIRTY(palDirty[1], addr);
@ -333,7 +333,7 @@ void CTileGen::InitPalette(void)
for (int i = 0; i < 0x20000/4; i++) for (int i = 0; i < 0x20000/4; i++)
{ {
WritePalette(i, *(UINT32 *) &vram[0x100000 + i*4]); WritePalette(i, *(UINT32 *) &vram[0x100000 + i*4]);
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
{ {
palRO[0][i] = pal[0][i]; palRO[0][i] = pal[0][i];
palRO[1][i] = pal[1][i]; palRO[1][i] = pal[1][i];
@ -444,7 +444,7 @@ void CTileGen::WriteRegister(unsigned reg, UINT32 data)
void CTileGen::Reset(void) void CTileGen::Reset(void)
{ {
unsigned memSize = (g_Config.gpuMultiThreaded ? MEMORY_POOL_SIZE : MEM_POOL_SIZE_RW); unsigned memSize = (m_gpuMultiThreaded ? MEMORY_POOL_SIZE : MEM_POOL_SIZE_RW);
memset(memoryPool, 0, memSize); memset(memoryPool, 0, memSize);
memset(regs, 0, sizeof(regs)); memset(regs, 0, sizeof(regs));
memset(regsRO, 0, sizeof(regsRO)); memset(regsRO, 0, sizeof(regsRO));
@ -465,7 +465,7 @@ void CTileGen::AttachRenderer(CRender2D *Render2DPtr)
Render2D = Render2DPtr; Render2D = Render2DPtr;
// If multi-threaded, attach read-only snapshots to renderer instead of real ones // If multi-threaded, attach read-only snapshots to renderer instead of real ones
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
{ {
Render2D->AttachVRAM(vramRO); Render2D->AttachVRAM(vramRO);
Render2D->AttachPalette((const UINT32 **)palRO); Render2D->AttachPalette((const UINT32 **)palRO);
@ -484,7 +484,7 @@ void CTileGen::AttachRenderer(CRender2D *Render2DPtr)
bool CTileGen::Init(CIRQ *IRQObjectPtr) bool CTileGen::Init(CIRQ *IRQObjectPtr)
{ {
unsigned memSize = (g_Config.gpuMultiThreaded ? MEMORY_POOL_SIZE : MEM_POOL_SIZE_RW); unsigned memSize = (m_gpuMultiThreaded ? MEMORY_POOL_SIZE : MEM_POOL_SIZE_RW);
float memSizeMB = (float)memSize/(float)0x100000; float memSizeMB = (float)memSize/(float)0x100000;
// Allocate all memory for all TileGen RAM regions // Allocate all memory for all TileGen RAM regions
@ -498,7 +498,7 @@ bool CTileGen::Init(CIRQ *IRQObjectPtr)
pal[1] = (UINT32 *) &memoryPool[OFFSET_PAL_B]; pal[1] = (UINT32 *) &memoryPool[OFFSET_PAL_B];
// If multi-threaded, set up pointers for read-only snapshots and dirty page arrays too // If multi-threaded, set up pointers for read-only snapshots and dirty page arrays too
if (g_Config.gpuMultiThreaded) if (m_gpuMultiThreaded)
{ {
vramRO = (UINT8 *) &memoryPool[OFFSET_VRAM_RO]; vramRO = (UINT8 *) &memoryPool[OFFSET_VRAM_RO];
palRO[0] = (UINT32 *) &memoryPool[OFFSET_PAL_RO_A]; palRO[0] = (UINT32 *) &memoryPool[OFFSET_PAL_RO_A];
@ -515,7 +515,9 @@ bool CTileGen::Init(CIRQ *IRQObjectPtr)
return OKAY; return OKAY;
} }
CTileGen::CTileGen(void) CTileGen::CTileGen(const Util::Config::Node &config)
: m_config(config),
m_gpuMultiThreaded(config["GPUMultiThreaded"].ValueAs<bool>())
{ {
IRQ = NULL; IRQ = NULL;
memoryPool = NULL; memoryPool = NULL;

View file

@ -238,12 +238,16 @@ public:
bool Init(CIRQ *IRQObjectPtr); bool Init(CIRQ *IRQObjectPtr);
/* /*
* CTileGen(void): * CTileGen(config):
* ~CTileGen(void): * ~CTileGen(void):
* *
* Constructor and destructor. * Constructor and destructor.
*
* Paramters:
* config Run-time configuration. The reference should be held because
* this changes at run-time.
*/ */
CTileGen(void); CTileGen(const Util::Config::Node &config);
~CTileGen(void); ~CTileGen(void);
private: private:
@ -253,7 +257,10 @@ private:
void WritePalette(unsigned color, UINT32 data); void WritePalette(unsigned color, UINT32 data);
UINT32 UpdateSnapshots(bool copyWhole); UINT32 UpdateSnapshots(bool copyWhole);
UINT32 UpdateSnapshot(bool copyWhole, UINT8 *src, UINT8 *dst, unsigned size, UINT8 *dirty); UINT32 UpdateSnapshot(bool copyWhole, UINT8 *src, UINT8 *dst, unsigned size, UINT8 *dirty);
const Util::Config::Node &m_config;
const bool m_gpuMultiThreaded;
CIRQ *IRQ; // IRQ controller the tile generator is attached to CIRQ *IRQ; // IRQ controller the tile generator is attached to
CRender2D *Render2D; // 2D renderer the tile generator is attached to CRender2D *Render2D; // 2D renderer the tile generator is attached to

View file

@ -46,7 +46,7 @@ extern bool OpenAudio();
* *
* Sends a chunk of two-channel audio with the given number of samples to the audio system. * Sends a chunk of two-channel audio with the given number of samples to the audio system.
*/ */
extern bool OutputAudio(unsigned numSamples, INT16 *leftBuffer, INT16 *rightBuffer); extern bool OutputAudio(unsigned numSamples, INT16 *leftBuffer, INT16 *rightBuffer, bool flipStereo);
/* /*
* CloseAudio() * CloseAudio()

View file

@ -67,12 +67,12 @@ COutputs::~COutputs()
// //
} }
const GameInfo *COutputs::GetGame() const const Game &COutputs::GetGame() const
{ {
return m_game; return m_game;
} }
void COutputs::SetGame(const GameInfo *game) void COutputs::SetGame(const Game &game)
{ {
m_game = game; m_game = game;
} }

View file

@ -1,55 +1,55 @@
/** /**
** Supermodel ** Supermodel
** A Sega Model 3 Arcade Emulator. ** A Sega Model 3 Arcade Emulator.
** Copyright 2011 Bart Trzynadlowski, Nik Henson ** Copyright 2011 Bart Trzynadlowski, Nik Henson
** **
** This file is part of Supermodel. ** This file is part of Supermodel.
** **
** Supermodel is free software: you can redistribute it and/or modify it under ** 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 ** 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) ** Software Foundation, either version 3 of the License, or (at your option)
** any later version. ** any later version.
** **
** Supermodel is distributed in the hope that it will be useful, but WITHOUT ** Supermodel is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
** more details. ** more details.
** **
** You should have received a copy of the GNU General Public License along ** You should have received a copy of the GNU General Public License along
** with Supermodel. If not, see <http://www.gnu.org/licenses/>. ** with Supermodel. If not, see <http://www.gnu.org/licenses/>.
**/ **/
/* /*
* Outputs.h * Outputs.h
* *
* Base class for outputs. * Base class for outputs.
*/ */
#ifndef INCLUDED_OUTPUTS_H #ifndef INCLUDED_OUTPUTS_H
#define INCLUDED_OUTPUTS_H #define INCLUDED_OUTPUTS_H
/* #include "Game.h"
* EOutputs enumeration of all available outputs.
* Currently just contains the outputs for the driving games - more will need to be added for the other games. /*
*/ * EOutputs enumeration of all available outputs.
enum EOutputs * Currently just contains the outputs for the driving games - more will need to be added for the other games.
{ */
OutputUnknown = -1, enum EOutputs
OutputPause = 0, {
OutputLampStart, OutputUnknown = -1,
OutputLampView1, OutputPause = 0,
OutputLampView2, OutputLampStart,
OutputLampView3, OutputLampView1,
OutputLampView4, OutputLampView2,
OutputLampLeader, OutputLampView3,
OutputRawDrive, OutputLampView4,
OutputRawLamps OutputLampLeader,
}; OutputRawDrive,
OutputRawLamps
#define NUM_OUTPUTS 9 };
struct GameInfo; #define NUM_OUTPUTS 9
class COutputs class COutputs
{ {
public: public:
@ -95,14 +95,14 @@ public:
* *
* Returns the currently running game. * Returns the currently running game.
*/ */
const GameInfo *GetGame() const; const Game &GetGame() const;
/* /*
* SetGame(game): * SetGame(game):
* *
* Sets the currently running game. * Sets the currently running game.
*/ */
void SetGame(const GameInfo *game); void SetGame(const Game &game);
/* /*
* GetValue(output): * GetValue(output):
@ -137,7 +137,7 @@ protected:
private: private:
static const char* s_outputNames[]; // Static array of output names static const char* s_outputNames[]; // Static array of output names
const GameInfo *m_game; // Currently running game Game m_game; // Currently running game
bool m_first[NUM_OUTPUTS]; // For each output, true if an initial value has been set bool m_first[NUM_OUTPUTS]; // For each output, true if an initial value has been set
UINT8 m_values[NUM_OUTPUTS]; // Current value of each output UINT8 m_values[NUM_OUTPUTS]; // Current value of each output
}; };

View file

@ -190,7 +190,7 @@ static void PlayCallback(void *data, Uint8 *stream, int len)
callback(callbackData); callback(callbackData);
} }
static void MixChannels(unsigned numSamples, INT16 *leftBuffer, INT16 *rightBuffer, void *dest) static void MixChannels(unsigned numSamples, INT16 *leftBuffer, INT16 *rightBuffer, void *dest, bool flipStereo)
{ {
INT16 *p = (INT16*)dest; INT16 *p = (INT16*)dest;
@ -198,7 +198,7 @@ static void MixChannels(unsigned numSamples, INT16 *leftBuffer, INT16 *rightBuff
for (unsigned i = 0; i < numSamples; i++) for (unsigned i = 0; i < numSamples; i++)
*p++ = leftBuffer[i] + rightBuffer[i]; // TODO: these should probably be clipped! *p++ = leftBuffer[i] + rightBuffer[i]; // TODO: these should probably be clipped!
#else #else
if (g_Config.flipStereo) // swap left and right channels if (flipStereo) // swap left and right channels
{ {
for (unsigned i = 0; i < numSamples; i++) for (unsigned i = 0; i < numSamples; i++)
{ {
@ -280,7 +280,7 @@ bool OpenAudio()
return OKAY; return OKAY;
} }
bool OutputAudio(unsigned numSamples, INT16 *leftBuffer, INT16 *rightBuffer) bool OutputAudio(unsigned numSamples, INT16 *leftBuffer, INT16 *rightBuffer, bool flipStereo)
{ {
//printf("OutputAudio(%u) [writePos = %u, writeWrapped = %s, playPos = %u, audioBufferSize = %u]\n", //printf("OutputAudio(%u) [writePos = %u, writeWrapped = %s, playPos = %u, audioBufferSize = %u]\n",
// numSamples, writePos, (writeWrapped ? "true" : "false"), playPos, audioBufferSize); // numSamples, writePos, (writeWrapped ? "true" : "false"), playPos, audioBufferSize);
@ -295,7 +295,7 @@ bool OutputAudio(unsigned numSamples, INT16 *leftBuffer, INT16 *rightBuffer)
// Mix together left and right channels into single chunk of data // Mix together left and right channels into single chunk of data
INT16 mixBuffer[NUM_CHANNELS * SAMPLES_PER_FRAME]; INT16 mixBuffer[NUM_CHANNELS * SAMPLES_PER_FRAME];
MixChannels(numSamples, leftBuffer, rightBuffer, mixBuffer); MixChannels(numSamples, leftBuffer, rightBuffer, mixBuffer, flipStereo);
// Lock SDL audio callback so that it doesn't interfere with following code // Lock SDL audio callback so that it doesn't interfere with following code
SDL_LockAudio(); SDL_LockAudio();

File diff suppressed because it is too large Load diff

View file

@ -1,174 +0,0 @@
/**
** Supermodel
** A Sega Model 3 Arcade Emulator.
** Copyright 2011-2016 Bart Trzynadlowski, Nik Henson
**
** 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/>.
**/
/*
* OSDConfig.h
*
* Header file defining the COSDConfig class: OSD configuration settings,
* inherited by CConfig.
*/
#ifndef INCLUDED_OSDCONFIG_H
#define INCLUDED_OSDCONFIG_H
#include <string>
#include "Supermodel.h"
using namespace std;
/*
* COSDConfig:
*
* Settings used by COSDConfig.
*/
class COSDConfig
{
public:
bool new3DEngine; // New 3D engine
unsigned xRes, yRes; // X and Y resolution, in pixels
bool fullScreen; // Full screen mode (if true)
bool wideScreen; // Wide screen hack
bool vsync; // Enable v-sync
bool throttle; // 60 Hz frame limiting
bool showFPS; // Show frame rate
unsigned crosshairs; // For game guns: 0 = no crosshairs, 1 = player 1 only, 2 = player 2 only, 3 = both players
bool flipStereo; // Flip stereo channels
#ifdef SUPERMODEL_DEBUGGER
bool disableDebugger; // disables the debugger (not stored in the config. file)
#endif
#ifdef SUPERMODEL_WIN32
unsigned dInputConstForceLeftMax;
unsigned dInputConstForceRightMax;
unsigned dInputSelfCenterMax;
unsigned dInputFrictionMax;
unsigned dInputVibrateMax;
unsigned xInputConstForceThreshold;
unsigned xInputConstForceMax;
unsigned xInputVibrateMax;
#endif
// Input system
inline void SetInputSystem(const char *inpSysName)
{
if (inpSysName == NULL)
{
#ifdef SUPERMODEL_WIN32 // default is DirectInput on Windows
inputSystem = "dinput";
#else // everyone else uses SDL
inputSystem = "sdl";
#endif
return;
}
if (stricmp(inpSysName,"sdl")
#ifdef SUPERMODEL_WIN32
&& stricmp(inpSysName,"dinput") && stricmp(inpSysName,"xinput") && stricmp(inpSysName,"rawinput")
#endif
)
{
#ifdef SUPERMODEL_WIN32
ErrorLog("Unknown input system '%s', defaulting to DirectInput.", inpSysName);
inputSystem = "dinput";
#else
ErrorLog("Unknown input system '%s', defaulting to SDL.", inpSysName);
inputSystem = "sdl";
#endif
return;
}
inputSystem = inpSysName;
}
inline const char *GetInputSystem(void)
{
return inputSystem.c_str();
}
// Outputs
inline void SetOutputs(const char *outputsName)
{
if (outputsName == NULL)
{
outputs = "none";
return;
}
if (stricmp(outputsName, "none")
#ifdef SUPERMODEL_WIN32
&& stricmp(outputsName, "win")
#endif
)
{
ErrorLog("Unknown outputs '%s', defaulting to None.", outputsName);
outputs = "none";
return;
}
outputs = outputsName;
}
inline const char *GetOutputs(void)
{
return outputs.c_str();
}
// Defaults
COSDConfig(void)
{
new3DEngine = false;
xRes = 496;
yRes = 384;
fullScreen = false;
wideScreen = false;
vsync = true;
throttle = true;
showFPS = false;
crosshairs = 0;
flipStereo = false;
#ifdef SUPERMODEL_DEBUGGER
disableDebugger = false;
#endif
#ifdef SUPERMODEL_WIN32
inputSystem = "dinput";
dInputConstForceLeftMax = 100;
dInputConstForceRightMax = 100;
dInputSelfCenterMax = 100;
dInputFrictionMax = 100;
dInputVibrateMax = 100;
xInputConstForceThreshold = 30;
xInputConstForceMax = 100;
xInputVibrateMax = 100;
#else
inputSystem = "sdl";
#endif
outputs = "none";
}
private:
string inputSystem;
string outputs;
};
#endif // INCLUDED_OSDCONFIG_H

View file

@ -182,7 +182,13 @@ SDLKeyMapStruct CSDLInputSystem::s_keyMap[] =
{ "UNDO", SDLK_UNDO } { "UNDO", SDLK_UNDO }
}; };
CSDLInputSystem::CSDLInputSystem() : CInputSystem("SDL"), m_keyState(NULL), m_mouseX(0), m_mouseY(0), m_mouseZ(0), m_mouseButtons(0) CSDLInputSystem::CSDLInputSystem()
: CInputSystem("SDL"),
m_keyState(NULL),
m_mouseX(0),
m_mouseY(0),
m_mouseZ(0),
m_mouseButtons(0)
{ {
// //
} }

View file

@ -428,8 +428,9 @@ const char *CDirectInputSystem::ConstructName(bool useRawInput, bool useXInput)
return (useXInput ? "Xinput" : "DirectInput"); return (useXInput ? "Xinput" : "DirectInput");
} }
CDirectInputSystem::CDirectInputSystem(bool useRawInput, bool useXInput) : CDirectInputSystem::CDirectInputSystem(const Util::Config::Node &config, bool useRawInput, bool useXInput) :
CInputSystem(ConstructName(useRawInput, useXInput)), CInputSystem(ConstructName(useRawInput, useXInput)),
m_config(config),
m_useRawInput(useRawInput), m_useXInput(useXInput), m_enableFFeedback(true), m_useRawInput(useRawInput), m_useXInput(useXInput), m_enableFFeedback(true),
m_initializedCOM(false), m_activated(false), m_hwnd(NULL), m_screenW(0), m_screenH(0), m_initializedCOM(false), m_activated(false), m_hwnd(NULL), m_screenW(0), m_screenH(0),
m_getRIDevListPtr(NULL), m_getRIDevInfoPtr(NULL), m_regRIDevsPtr(NULL), m_getRIDataPtr(NULL), m_getRIDevListPtr(NULL), m_getRIDevInfoPtr(NULL), m_regRIDevsPtr(NULL), m_getRIDataPtr(NULL),
@ -1791,13 +1792,15 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
break; break;
case FFConstantForce: case FFConstantForce:
{
// Check if constant force effect is disabled // Check if constant force effect is disabled
if (g_Config.xInputConstForceMax == 0) unsigned xInputConstForceMax = m_config["XInputConstForceMax"].ValueAs<unsigned>();
if (xInputConstForceMax == 0)
return false; return false;
// Constant force effect is mapped to either left or right vibration motor depending on its direction // Constant force effect is mapped to either left or right vibration motor depending on its direction
negForce = ffCmd.force < 0.0f; negForce = ffCmd.force < 0.0f;
absForce = (negForce ? -ffCmd.force : ffCmd.force); absForce = (negForce ? -ffCmd.force : ffCmd.force);
threshold = (float)g_Config.xInputConstForceThreshold / 100.0f; threshold = (float)m_config["XInputConstForceThreshold"].ValueAs<unsigned>() / 100.0f;
// Check if constant force effect is being stopped or is below threshold // Check if constant force effect is being stopped or is below threshold
if (absForce == 0.0f || absForce < threshold) if (absForce == 0.0f || absForce < threshold)
{ {
@ -1808,25 +1811,27 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
else if (negForce) else if (negForce)
{ {
// If force is negative (to left), set left motor vibrating // If force is negative (to left), set left motor vibrating
pInfo->xiConstForceLeft = (WORD)(absForce * (float)(g_Config.xInputConstForceMax * XI_VIBRATE_SCALE)); pInfo->xiConstForceLeft = (WORD)(absForce * (float)(xInputConstForceMax * XI_VIBRATE_SCALE));
pInfo->xiConstForceRight = 0; pInfo->xiConstForceRight = 0;
} }
else else
{ {
// If force positive (to right), set right motor vibrating // If force positive (to right), set right motor vibrating
pInfo->xiConstForceLeft = 0; pInfo->xiConstForceLeft = 0;
pInfo->xiConstForceRight = (WORD)(absForce * (float)(g_Config.xInputConstForceMax * XI_VIBRATE_SCALE)); pInfo->xiConstForceRight = (WORD)(absForce * (float)(xInputConstForceMax * XI_VIBRATE_SCALE));
} }
break; break;
}
case FFSelfCenter: case FFSelfCenter:
case FFFriction: case FFFriction:
// Self center and friction effects are not mapped // Self center and friction effects are not mapped
return false; return false;
case FFVibrate: case FFVibrate:
// Check if vibration effect is disabled {
if (g_Config.xInputVibrateMax == 0) // Check if vibration effect is disabled
unsigned xInputVibrateMax = m_config["XInputVibrateMax"].ValueAs<unsigned>();
if (xInputVibrateMax == 0)
return false; return false;
// Check if vibration effect is being stopped // Check if vibration effect is being stopped
if (ffCmd.force == 0.0f) if (ffCmd.force == 0.0f)
@ -1837,10 +1842,10 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
else else
{ {
// Otherwise, set both motors vibrating // Otherwise, set both motors vibrating
pInfo->xiVibrateBoth = (WORD)(ffCmd.force * (float)(g_Config.xInputVibrateMax * XI_VIBRATE_SCALE)); pInfo->xiVibrateBoth = (WORD)(ffCmd.force * (float)(xInputVibrateMax * XI_VIBRATE_SCALE));
} }
break; break;
}
default: default:
// Unknown feedback command // Unknown feedback command
return false; return false;
@ -1893,16 +1898,18 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
//printf("FFConstantForce %0.2f\n", 100.0f * ffCmd.force); //printf("FFConstantForce %0.2f\n", 100.0f * ffCmd.force);
if (ffCmd.force >= 0.0f) if (ffCmd.force >= 0.0f)
{ {
if (g_Config.dInputConstForceRightMax == 0) unsigned dInputConstForceRightMax = m_config["DirectInputConstForceRightMax"].ValueAs<unsigned>();
if (dInputConstForceRightMax == 0)
return false; return false;
lFFMag = (LONG)(-ffCmd.force * (float)(g_Config.dInputConstForceRightMax * DI_EFFECTS_SCALE)); // Invert sign for DirectInput effect lFFMag = (LONG)(-ffCmd.force * (float)(dInputConstForceRightMax * DI_EFFECTS_SCALE)); // Invert sign for DirectInput effect
dicf.lMagnitude = std::max<LONG>(lFFMag, -DI_EFFECTS_MAX); dicf.lMagnitude = std::max<LONG>(lFFMag, -DI_EFFECTS_MAX);
} }
else else
{ {
if (g_Config.dInputConstForceLeftMax == 0) unsigned dInputConstForceLeftMax = m_config["DirectInputConstForceLeftMax"].ValueAs<unsigned>();
if (dInputConstForceLeftMax == 0)
return false; return false;
lFFMag = (LONG)(-ffCmd.force * (float)(g_Config.dInputConstForceLeftMax * DI_EFFECTS_SCALE)); // Invert sign for DirectInput effect lFFMag = (LONG)(-ffCmd.force * (float)(dInputConstForceLeftMax * DI_EFFECTS_SCALE)); // Invert sign for DirectInput effect
dicf.lMagnitude = std::min<LONG>(lFFMag, DI_EFFECTS_MAX); dicf.lMagnitude = std::min<LONG>(lFFMag, DI_EFFECTS_MAX);
} }
@ -1911,10 +1918,12 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
break; break;
case FFSelfCenter: case FFSelfCenter:
{
unsigned dInputSelfCenterMax = m_config["DirectInputSelfCenterMax"].ValueAs<unsigned>();
//printf("FFSelfCenter %0.2f\n", 100.0f * ffCmd.force); //printf("FFSelfCenter %0.2f\n", 100.0f * ffCmd.force);
if (g_Config.dInputSelfCenterMax == 0) if (dInputSelfCenterMax == 0)
return false; return false;
lFFMag = (LONG)(ffCmd.force * (float)(g_Config.dInputSelfCenterMax * DI_EFFECTS_SCALE)); lFFMag = (LONG)(ffCmd.force * (float)(dInputSelfCenterMax * DI_EFFECTS_SCALE));
dic.lOffset = 0; dic.lOffset = 0;
dic.lPositiveCoefficient = std::max<LONG>(0, std::min<LONG>(lFFMag, DI_EFFECTS_MAX)); dic.lPositiveCoefficient = std::max<LONG>(0, std::min<LONG>(lFFMag, DI_EFFECTS_MAX));
dic.lNegativeCoefficient = std::max<LONG>(0, std::min<LONG>(lFFMag, DI_EFFECTS_MAX)); dic.lNegativeCoefficient = std::max<LONG>(0, std::min<LONG>(lFFMag, DI_EFFECTS_MAX));
@ -1925,12 +1934,14 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
eff.cbTypeSpecificParams = sizeof(DICONDITION); eff.cbTypeSpecificParams = sizeof(DICONDITION);
eff.lpvTypeSpecificParams = &dic; eff.lpvTypeSpecificParams = &dic;
break; break;
}
case FFFriction: case FFFriction:
{
unsigned dInputFrictionMax = m_config["DirectInputFrictionMax"].ValueAs<unsigned>();
//printf("FFFriction %0.2f\n", 100.0f * ffCmd.force); //printf("FFFriction %0.2f\n", 100.0f * ffCmd.force);
if (g_Config.dInputFrictionMax == 0) if (dInputFrictionMax == 0)
return false; return false;
lFFMag = (LONG)(ffCmd.force * (float)(g_Config.dInputFrictionMax * DI_EFFECTS_SCALE)); lFFMag = (LONG)(ffCmd.force * (float)(dInputFrictionMax * DI_EFFECTS_SCALE));
dic.lOffset = 0; dic.lOffset = 0;
dic.lPositiveCoefficient = std::max<LONG>(0, std::min<LONG>(lFFMag, DI_EFFECTS_MAX)); dic.lPositiveCoefficient = std::max<LONG>(0, std::min<LONG>(lFFMag, DI_EFFECTS_MAX));
dic.lNegativeCoefficient = std::max<LONG>(0, std::min<LONG>(lFFMag, DI_EFFECTS_MAX)); dic.lNegativeCoefficient = std::max<LONG>(0, std::min<LONG>(lFFMag, DI_EFFECTS_MAX));
@ -1941,12 +1952,14 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
eff.cbTypeSpecificParams = sizeof(DICONDITION); eff.cbTypeSpecificParams = sizeof(DICONDITION);
eff.lpvTypeSpecificParams = &dic; eff.lpvTypeSpecificParams = &dic;
break; break;
}
case FFVibrate: case FFVibrate:
{
unsigned dInputVibrateMax = m_config["DirectInputVibrateMax"].ValueAs<unsigned>();
//printf("FFVibrate %0.2f\n", 100.0f * ffCmd.force); //printf("FFVibrate %0.2f\n", 100.0f * ffCmd.force);
if (g_Config.dInputVibrateMax == 0) if (dInputVibrateMax == 0)
return false; return false;
dFFMag = (DWORD)(ffCmd.force * (float)(g_Config.dInputVibrateMax * DI_EFFECTS_SCALE)); dFFMag = (DWORD)(ffCmd.force * (float)(dInputVibrateMax * DI_EFFECTS_SCALE));
dip.dwMagnitude = std::max<DWORD>(0, std::min<DWORD>(dFFMag, DI_EFFECTS_MAX)); dip.dwMagnitude = std::max<DWORD>(0, std::min<DWORD>(dFFMag, DI_EFFECTS_MAX));
dip.lOffset = 0; dip.lOffset = 0;
dip.dwPhase = 0; dip.dwPhase = 0;
@ -1955,7 +1968,7 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
eff.cbTypeSpecificParams = sizeof(DIPERIODIC); eff.cbTypeSpecificParams = sizeof(DIPERIODIC);
eff.lpvTypeSpecificParams = &dip; eff.lpvTypeSpecificParams = &dip;
break; break;
}
default: default:
// Unknown feedback command // Unknown feedback command
return false; return false;

View file

@ -108,6 +108,8 @@ typedef /*WINUSERAPI*/ DWORD (WINAPI *XInputSetStatePtr)(IN DWORD dwUserIndex, I
class CDirectInputSystem : public CInputSystem class CDirectInputSystem : public CInputSystem
{ {
private: private:
const Util::Config::Node &m_config;
// Lookup table to map key names to DirectInput keycodes and Virtual keycodes // Lookup table to map key names to DirectInput keycodes and Virtual keycodes
static DIKeyMapStruct s_keyMap[]; static DIKeyMapStruct s_keyMap[];
@ -232,7 +234,7 @@ public:
* to the same shared axis and so cannot be distinguished when pressed together. * to the same shared axis and so cannot be distinguished when pressed together.
* If enableFFeedback is true then force feedback is enabled (for those joysticks which are force feedback capable). * If enableFFeedback is true then force feedback is enabled (for those joysticks which are force feedback capable).
*/ */
CDirectInputSystem(bool useRawInput, bool useXInput); CDirectInputSystem(const Util::Config::Node &config, bool useRawInput, bool useXInput);
~CDirectInputSystem(); ~CDirectInputSystem();

View file

@ -221,23 +221,19 @@ LRESULT CWinOutputs::UnregisterClient(HWND hwnd, LPARAM id)
LRESULT CWinOutputs::SendIdString(HWND hwnd, LPARAM id) LRESULT CWinOutputs::SendIdString(HWND hwnd, LPARAM id)
{ {
// Id 0 is the name of the game // Id 0 is the name of the game
const char *name; std::string name;
if (id == 0) if (id == 0)
name = GetGame()->id; name = GetGame().name;
else else
name = MapIdToName(id); name = MapIdToName(id) ? MapIdToName(id) : "";
// NULL name is an empty string
if (name == NULL)
name = "";
// Allocate memory for message // Allocate memory for message
int dataLen = sizeof(CopyDataIdString) + strlen(name); int dataLen = sizeof(CopyDataIdString) + name.length();
CopyDataIdString *data = (CopyDataIdString*)new(nothrow) UINT8[dataLen]; CopyDataIdString *data = (CopyDataIdString*)new(nothrow) UINT8[dataLen];
if (!data) if (!data)
return 1; return 1;
data->id = id; data->id = id;
strcpy(data->string, name); strcpy(data->string, name.c_str());
// Reply by using SendMessage with WM_COPYDATA // Reply by using SendMessage with WM_COPYDATA
COPYDATASTRUCT copyData; COPYDATASTRUCT copyData;

View file

@ -57,6 +57,9 @@
#include <cmath> #include <cmath>
#include "Sound/SCSPDSP.h" #include "Sound/SCSPDSP.h"
static const Util::Config::Node *s_config = 0;
static bool s_multiThreaded = false;
//#define NEWSCSP //#define NEWSCSP
//#define RB_VOLUME //#define RB_VOLUME
@ -552,8 +555,11 @@ void SCSP_StopSlot(_SLOT *slot,int keyoff)
#define log2(n) (log((float) n)/log((float) 2)) #define log2(n) (log((float) n)/log((float) 2))
bool SCSP_Init(int n) bool SCSP_Init(const Util::Config::Node &config, int n)
{ {
s_config = &config;
s_multiThreaded = config["MultiThreaded"].ValueAs<bool>();
if(n==2) if(n==2)
{ {
SCSP=SCSPs+1; SCSP=SCSPs+1;
@ -928,7 +934,7 @@ void SCSP_UpdateRegR(int reg)
/* /*
* MIDI FIFO critical section! * MIDI FIFO critical section!
*/ */
if (g_Config.multiThreaded) if (s_multiThreaded)
MIDILock->Lock(); MIDILock->Lock();
v|=MidiStack[MidiR]; v|=MidiStack[MidiR];
@ -943,7 +949,7 @@ void SCSP_UpdateRegR(int reg)
MidiInFill--; MidiInFill--;
SCSP->data[0x5/2]=v; SCSP->data[0x5/2]=v;
if (g_Config.multiThreaded) if (s_multiThreaded)
MIDILock->Unlock(); MIDILock->Unlock();
} }
break; break;
@ -1770,7 +1776,12 @@ void SCSP_DoMasterSamples(int nsamples)
* When one SCSP is fully attenuated, the other's samples will be multiplied * When one SCSP is fully attenuated, the other's samples will be multiplied
* by 2. * by 2.
*/ */
float balance = (float) g_Config.GetSCSPBalance() / 100.0f; float balance = (float) s_config->Get("Balance").ValueAs<float>();
if (balance < -100.0f)
balance = -100.0f;
else if (balance > 100.0f)
balance = 100.0f;
balance /= 100.0f;
float masterBalance = 1.0f+balance; float masterBalance = 1.0f+balance;
float slaveBalance = 1.0f-balance; float slaveBalance = 1.0f-balance;
@ -1935,7 +1946,7 @@ void SCSP_MidiIn(BYTE val)
/* /*
* MIDI FIFO critical section * MIDI FIFO critical section
*/ */
if (g_Config.multiThreaded) if (s_multiThreaded)
MIDILock->Lock(); MIDILock->Lock();
//DebugLog("Midi Buffer push %02X",val); //DebugLog("Midi Buffer push %02X",val);
@ -1945,7 +1956,7 @@ void SCSP_MidiIn(BYTE val)
//Int68kCB(IrqMidi); //Int68kCB(IrqMidi);
// SCSP.data[0x20/2]|=0x8; // SCSP.data[0x20/2]|=0x8;
if (g_Config.multiThreaded) if (s_multiThreaded)
MIDILock->Unlock(); MIDILock->Unlock();
} }
@ -1954,7 +1965,7 @@ void SCSP_MidiOutW(BYTE val)
/* /*
* MIDI FIFO critical section * MIDI FIFO critical section
*/ */
if (g_Config.multiThreaded) if (s_multiThreaded)
MIDILock->Lock(); MIDILock->Lock();
//printf("68K: MIDI out\n"); //printf("68K: MIDI out\n");
@ -1963,7 +1974,7 @@ void SCSP_MidiOutW(BYTE val)
MidiOutW&=7; MidiOutW&=7;
++MidiOutFill; ++MidiOutFill;
if (g_Config.multiThreaded) if (s_multiThreaded)
MIDILock->Unlock(); MIDILock->Unlock();
} }
@ -1978,7 +1989,7 @@ unsigned char SCSP_MidiOutR()
/* /*
* MIDI FIFO critical section * MIDI FIFO critical section
*/ */
if (g_Config.multiThreaded) if (s_multiThreaded)
MIDILock->Lock(); MIDILock->Lock();
val=MidiStack[MidiOutR++]; val=MidiStack[MidiOutR++];
@ -1986,7 +1997,7 @@ unsigned char SCSP_MidiOutR()
MidiOutR&=7; MidiOutR&=7;
--MidiOutFill; --MidiOutFill;
if (g_Config.multiThreaded) if (s_multiThreaded)
MIDILock->Unlock(); MIDILock->Unlock();
return val; return val;
@ -1999,12 +2010,12 @@ unsigned char SCSP_MidiOutFill()
/* /*
* MIDI FIFO critical section * MIDI FIFO critical section
*/ */
if (g_Config.multiThreaded) if (s_multiThreaded)
MIDILock->Lock(); MIDILock->Lock();
v = MidiOutFill; v = MidiOutFill;
if (g_Config.multiThreaded) if (s_multiThreaded)
MIDILock->Unlock(); MIDILock->Unlock();
return v; return v;
@ -2017,12 +2028,12 @@ unsigned char SCSP_MidiInFill()
/* /*
* MIDI FIFO critical section * MIDI FIFO critical section
*/ */
if (g_Config.multiThreaded) if (s_multiThreaded)
MIDILock->Lock(); MIDILock->Lock();
v = MidiInFill; v = MidiInFill;
if (g_Config.multiThreaded) if (s_multiThreaded)
MIDILock->Unlock(); MIDILock->Unlock();
return v; return v;

View file

@ -58,7 +58,7 @@ UINT8 SCSP_MidiOutR();
* Returns: * Returns:
* FAIL if an error occured (prints own error messages), OKAY otherwise. * FAIL if an error occured (prints own error messages), OKAY otherwise.
*/ */
bool SCSP_Init(int n); bool SCSP_Init(const Util::Config::Node &config, int n);
void SCSP_SetRAM(int n,UINT8 *r); void SCSP_SetRAM(int n,UINT8 *r);
void SCSP_RTECheck(); void SCSP_RTECheck();

View file

@ -97,9 +97,6 @@
// Error logging interface // Error logging interface
#include "OSD/Logger.h" #include "OSD/Logger.h"
// OSD configuration
#include "OSDConfig.h" // located in OSD/<port>/ directory
// OSD Interfaces // OSD Interfaces
#include "OSD/Thread.h" #include "OSD/Thread.h"
#include "OSD/Audio.h" #include "OSD/Audio.h"
@ -154,7 +151,6 @@
#include "Model3/DSB.h" #include "Model3/DSB.h"
#include "Model3/DriveBoard.h" #include "Model3/DriveBoard.h"
#include "Model3/Model3.h" #include "Model3/Model3.h"
#include "Config.h"
/****************************************************************************** /******************************************************************************