- Added crosshairs for light gun games and disabled mouse cursor in full screen mode (no way to re-enable it now).

- Fixed Real3D FIFO buffer overflow bug.
- Input system cannot be changed for non-Windows builds (only SDL is available).
- Added Spikeout-specific controls.
This commit is contained in:
Bart Trzynadlowski 2011-08-27 21:37:37 +00:00
parent b19f600fec
commit 8be2966ecb
10 changed files with 158 additions and 33 deletions

View file

@ -1497,7 +1497,7 @@ const struct GameInfo g_Model3GameList[] =
FALSE, // 96 MB of banked CROM (Do not Mirror)
0x4000000, // 64 MB of VROM
0x1000000, // 16 MB of sample ROMs
GAME_INPUT_COMMON|GAME_INPUT_JOYSTICK1|GAME_INPUT_FIGHTING,
GAME_INPUT_COMMON|GAME_INPUT_JOYSTICK1|GAME_INPUT_SPIKEOUT,
2, // DSB2 MPEG board
{
@ -1577,7 +1577,7 @@ const struct GameInfo g_Model3GameList[] =
FALSE, // 96 MB of banked CROM (Do not Mirror)
0x4000000, // 64 MB of VROM
0x1000000, // 16 MB of sample ROMs
GAME_INPUT_COMMON|GAME_INPUT_JOYSTICK1|GAME_INPUT_FIGHTING,
GAME_INPUT_COMMON|GAME_INPUT_JOYSTICK1|GAME_INPUT_SPIKEOUT,
2, // DSB2 MPEG board
{

View file

@ -50,7 +50,8 @@
#define GAME_INPUT_ANALOG_JOYSTICK 0x0400 // game has analog joystick
#define GAME_INPUT_TWIN_JOYSTICKS 0x0800 // game has twin joysticks
#define GAME_INPUT_SOCCER 0x1000 // game has soccer controls
#define GAME_INPUT_ALL 0x1FFF
#define GAME_INPUT_SPIKEOUT 0x2000 // game has Spikeout buttons
#define GAME_INPUT_ALL 0x3FFF
/******************************************************************************

View file

@ -58,8 +58,9 @@ const char* CInput::GetInputGroup()
case GAME_INPUT_UI: return "User Interface Controls";
case GAME_INPUT_COMMON: return "Common Controls";
case GAME_INPUT_JOYSTICK1: // Fall through to below
case GAME_INPUT_JOYSTICK2: return "8-Way Joysticks";
case GAME_INPUT_JOYSTICK2: return "4-Way Joysticks";
case GAME_INPUT_FIGHTING: return "Fighting Game Buttons";
case GAME_INPUT_SPIKEOUT: return "Spikeout Buttons";
case GAME_INPUT_SOCCER: return "Virtua Striker Buttons";
case GAME_INPUT_VEHICLE: return "Racing Game Steering Controls";
case GAME_INPUT_SHIFT4: return "Racing Game Gear Shift";

View file

@ -17,7 +17,7 @@ CInputs::CInputs(CInputSystem *system) : m_system(system)
uiLoadState = AddSwitchInput("UILoadState", "Load State", GAME_INPUT_UI, "KEY_F7");
uiDumpInpState = AddSwitchInput("UIDumpInputState", "Dump Input State", GAME_INPUT_UI, "KEY_F8");
uiClearNVRAM = AddSwitchInput("UIClearNVRAM", "Clear NVRAM", GAME_INPUT_UI, "KEY_ALT+KEY_N");
uiToggleCursor = AddSwitchInput("UIToggleCursor", "Toggle Cursor", 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");
#ifdef SUPERMODEL_DEBUGGER
uiEnterDebugger = AddSwitchInput("UIEnterDebugger", "Enter Debugger", GAME_INPUT_UI, "KEY_ALT+KEY_B");
@ -33,7 +33,7 @@ CInputs::CInputs(CInputSystem *system) : m_system(system)
test[0] = AddSwitchInput("TestA", "Test A", GAME_INPUT_COMMON, "KEY_6");
test[1] = AddSwitchInput("TestB", "Test B", GAME_INPUT_COMMON, "KEY_8");
// 8-Way Joysticks
// 4-Way Joysticks
up[0] = AddSwitchInput("JoyUp", "P1 Joystick Up", GAME_INPUT_JOYSTICK1, "KEY_UP,JOY1_UP");
down[0] = AddSwitchInput("JoyDown", "P1 Joystick Down", GAME_INPUT_JOYSTICK1, "KEY_DOWN,JOY1_DOWN");
left[0] = AddSwitchInput("JoyLeft", "P1 Joystick Left", GAME_INPUT_JOYSTICK1, "KEY_LEFT,JOY1_LEFT");
@ -53,6 +53,12 @@ CInputs::CInputs(CInputSystem *system) : m_system(system)
guard[1] = AddSwitchInput("Guard2", "P2 Guard", GAME_INPUT_FIGHTING, "JOY2_BUTTON3");
escape[1] = AddSwitchInput("Escape2", "P2 Escape", GAME_INPUT_FIGHTING, "JOY2_BUTTON4");
// Spikeout Buttons
shift = AddSwitchInput("Shift", "Shift", GAME_INPUT_SPIKEOUT, "KEY_A,JOY1_BUTTON1");
beat = AddSwitchInput("Beat", "Beat", GAME_INPUT_SPIKEOUT, "KEY_S,JOY1_BUTTON2");
charge = AddSwitchInput("Charge", "Charge",GAME_INPUT_SPIKEOUT, "KEY_D,JOY1_BUTTON3");
jump = AddSwitchInput("Jump", "Jump", GAME_INPUT_SPIKEOUT, "KEY_F,JOY1_BUTTON4");
// Virtua Striker Buttons
shortPass[0] = AddSwitchInput("ShortPass", "P1 Short Pass", GAME_INPUT_SOCCER, "KEY_A,JOY1_BUTTON1");
longPass[0] = AddSwitchInput("LongPass", "P1 Long Pass", GAME_INPUT_SOCCER, "KEY_S,JOY1_BUTTON2");

View file

@ -72,7 +72,7 @@ public:
CSwitchInput *uiLoadState;
CSwitchInput *uiDumpInpState;
CSwitchInput *uiClearNVRAM;
CSwitchInput *uiToggleCursor;
CSwitchInput *uiSelectCrosshairs;
CSwitchInput *uiToggleFrLimit;
#ifdef SUPERMODEL_DEBUGGER
CSwitchInput *uiEnterDebugger;
@ -96,6 +96,12 @@ public:
CSwitchInput *guard[2];
CSwitchInput *escape[2];
// Spikeout controls
CSwitchInput *shift;
CSwitchInput *beat;
CSwitchInput *charge;
CSwitchInput *jump;
// Soccer game controls (players 1 and 2)
CSwitchInput *shortPass[2];
CSwitchInput *longPass[2];
@ -140,7 +146,6 @@ public:
CSwitchInput *twinJoyJump;
CSwitchInput *twinJoyCrouch;
// Analog joystick
CAxisInput *analogJoyX;
CAxisInput *analogJoyY;

View file

@ -677,7 +677,7 @@ static const char *stateName[] =
void CDSB2::WriteMPEGFIFO(UINT8 byte)
{
printf("fifo: %x (state %s)\n", byte, stateName[mpegState]);
//printf("fifo: %x (state %s)\n", byte, stateName[mpegState]);
switch (mpegState)
{
case ST_IDLE:
@ -693,7 +693,7 @@ void CDSB2::WriteMPEGFIFO(UINT8 byte)
usingMPEGStart = mpegStart;
usingMPEGEnd = mpegEnd;
MPEG_PlayMemory((const char *) &mpegROM[mpegStart], mpegEnd-mpegStart);
printf("playing %X\n", mpegStart);
//printf("playing %X\n", mpegStart);
mpegState = ST_IDLE;
playing = 1;
}
@ -737,13 +737,13 @@ void CDSB2::WriteMPEGFIFO(UINT8 byte)
if (playing)
{
printf("Setting loop point to %x\n", mpegStart);
//printf("Setting loop point to %x\n", mpegStart);
usingLoopStart = mpegStart;
usingLoopEnd = mpegEnd-mpegStart;
MPEG_SetLoop((const char *) &mpegROM[usingLoopStart], usingLoopEnd);
}
printf("mpegStart=%x\n", mpegStart);
//printf("mpegStart=%x\n", mpegStart);
break;
case ST_GOT24:
mpegEnd &= 0x00FFFF;
@ -758,7 +758,7 @@ void CDSB2::WriteMPEGFIFO(UINT8 byte)
case ST_24_1:
mpegEnd &= 0xFFFF00;
mpegEnd |= (byte);
printf("mpegEnd=%x\n", mpegEnd);
//printf("mpegEnd=%x\n", mpegEnd);
// default to full stereo
// mixer_set_stereo_volume(0, 255, 255);
@ -781,7 +781,7 @@ void CDSB2::WriteMPEGFIFO(UINT8 byte)
usingMPEGStart = mpegStart;
usingMPEGEnd = mpegEnd;
MPEG_PlayMemory((const char *) &mpegROM[mpegStart], mpegEnd-mpegStart);
printf("playing %X (from st_gota4)\n", mpegStart);
//printf("playing %X (from st_gota4)\n", mpegStart);
playing = 1;
}
break;
@ -816,14 +816,14 @@ void CDSB2::WriteMPEGFIFO(UINT8 byte)
case ST_GOTB6: // rear left(?) volume
case ST_GOTB0: // left volume
volume[0] = byte;
printf("Set L Volume: %02X\n", byte);
//printf("Set L Volume: %02X\n", byte);
mpegState = ST_IDLE;
break;
case ST_GOTA7: // rear right(?) volume
case ST_GOTA1: // right volume
case ST_GOTA0:
volume[1] = byte;
printf("Set R Volume: %02X\n", byte);
//printf("Set R Volume: %02X\n", byte);
mpegState = ST_IDLE;
break;
case ST_GOTB2:
@ -929,7 +929,7 @@ void CDSB2::Write16(UINT32 addr, UINT16 data)
*(UINT16 *) &ram[addr] = data;
return;
}
printf("W16: %x @ %x\n", data, addr);
//printf("W16: %x @ %x\n", data, addr);
}
void CDSB2::Write32(UINT32 addr, UINT32 data)
@ -941,7 +941,7 @@ void CDSB2::Write32(UINT32 addr, UINT32 data)
*(UINT16 *) &ram[addr+2] = data&0xFFFF;
return;
}
printf("W32: %x @ %x\n", data, addr);
//printf("W32: %x @ %x\n", data, addr);
}
void CDSB2::SendCommand(UINT8 data)
@ -1023,7 +1023,7 @@ void CDSB2::Reset(void)
M68KSetContext(&M68K);
M68KReset();
printf("DSB2 PC=%06X\n", M68KGetPC());
//printf("DSB2 PC=%06X\n", M68KGetPC());
M68KGetContext(&M68K);
DebugLog("DSB2 Reset\n");

View file

@ -247,6 +247,14 @@ UINT8 CModel3::ReadInputs(unsigned reg)
data &= ~(Inputs->punch[0]->value<<0); // P1 Punch
}
if ((Game->inputFlags&GAME_INPUT_SPIKEOUT))
{
data &= ~(Inputs->shift->value<<2); // Shift
data &= ~(Inputs->beat->value<<0); // Beat
data &= ~(Inputs->charge->value<<1); // Charge
data &= ~(Inputs->jump->value<<3); // Jump
}
if ((Game->inputFlags&GAME_INPUT_SOCCER))
{
data &= ~(Inputs->shortPass[0]->value<<2); // P1 Short Pass
@ -2164,7 +2172,7 @@ void CModel3::RunMainBoardFrame(void)
++irqCount;
if (irqCount > 128)
{
printf("\tMIDI FIFO OVERFLOW! (IRQEn=%02X, IRQPend=%02X)\n", IRQ.ReadIRQEnable()&0x40, IRQ.ReadIRQState());
//printf("\tMIDI FIFO OVERFLOW! (IRQEn=%02X, IRQPend=%02X)\n", IRQ.ReadIRQEnable()&0x40, IRQ.ReadIRQState());
break;
}
}

View file

@ -132,6 +132,7 @@ void CReal3D::BeginFrame(void)
void CReal3D::EndFrame(void)
{
error = false; // clear error (just needs to be done once per frame)
status &= ~2;
Render3D->EndFrame();
}
@ -698,9 +699,14 @@ void CReal3D::Flush(void)
void CReal3D::WriteTextureFIFO(UINT32 data)
{
textureFIFO[fifoIdx++] = data;
if (fifoIdx >= (0x100000/4))
ErrorLog("Real3D texture FIFO maxed out!");
{
if (!error)
ErrorLog("Overflow in Real3D texture FIFO!");
error = true;
}
else
textureFIFO[fifoIdx++] = data;
}
void CReal3D::WriteTexturePort(unsigned reg, UINT32 data)
@ -797,6 +803,8 @@ void CReal3D::WritePCIConfigSpace(unsigned device, unsigned reg, unsigned bits,
void CReal3D::Reset(void)
{
error = false;
commandPortWritten = FALSE;
fifoIdx = 0;
@ -885,6 +893,7 @@ CReal3D::CReal3D(void)
textureRAM = NULL;
textureFIFO = NULL;
vrom = NULL;
error = false;
fifoIdx = 0;
vromTextureAddr = 0;
vromTextureHeader = 0;

View file

@ -351,6 +351,9 @@ private:
int step; // hardware stepping (as in GameInfo structure)
UINT32 pciID; // PCI vendor and device ID
// Error flag (to limit errors to once per frame)
bool error; // true if an error occurred this frame
// Real3D memory
UINT8 *memoryPool; // all memory allocated here
UINT32 *cullingRAMLo; // 4MB of culling RAM at 8C000000

View file

@ -1,3 +1,12 @@
//TODO before release:
// - Controls for Dirt Devils, and other recent games (is bass working?)
// - Crosshairs
// - Comment source code, clean up
// - BOOL -> bool, TRUE/FALSE -> true/false
// - Add option for building with /MD in MSVC Makefile
// - Remove SUPERMODEL_SOUND
// - EmulateSCSP -> EmulateSound ?
/**
** Supermodel
** A Sega Model 3 Arcade Emulator.
@ -571,6 +580,70 @@ static void LoadNVRAM(CModel3 *Model3)
}
/******************************************************************************
UI Rendering
Currently, only does crosshairs for light gun games.
******************************************************************************/
static void GunToViewCoords(float *x, float *y)
{
*x = (*x-150.0f)/(651.0f-150.0f); // Scale [150,651] -> [0.0,1.0]
*y = (*y-80.0f)/(465.0f-80.0f); // Scale [80,465] -> [0.0,1.0]
}
static void DrawCrosshair(float x, float y, float r, float g, float b)
{
glColor3f(r, g, b);
glVertex2f(x-0.01f, y);
glVertex2f(x-0.002f, y);
glVertex2f(x+0.003f, y);
glVertex2f(x+0.01f, y);
glVertex2f(x, y-0.01f*(float)xRes/(float)yRes);
glVertex2f(x, y-0.003f*(float)xRes/(float)yRes);
glVertex2f(x, y+0.002f*(float)xRes/(float)yRes);
glVertex2f(x, y+0.01f*(float)xRes/(float)yRes);
}
static void UpdateCrosshairs(CInputs *Inputs, unsigned showCrosshairs)
{
float x[2], y[2];
showCrosshairs &= 3;
if (!showCrosshairs)
return;
// Set up the viewport and orthogonal projection
glViewport(xOffset, yOffset, xRes, yRes);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_TEXTURE_2D); // no texture mapping
glDisable(GL_BLEND); // no blending
glDisable(GL_DEPTH_TEST); // no Z-buffering needed
glUseProgram(NULL); // no shaders
// Convert gun coordinates to viewspace coordinates
x[0] = (float) Inputs->gunX[0]->value;
y[0] = (float) Inputs->gunY[0]->value;
x[1] = (float) Inputs->gunX[1]->value;
y[1] = (float) Inputs->gunY[1]->value;
GunToViewCoords(&x[0], &y[0]);
GunToViewCoords(&x[1], &y[1]);
// Draw visible crosshairs
glBegin(GL_LINES);
glLineWidth(1.0f);
if ((showCrosshairs & 2) && !Inputs->trigger[0]->offscreenValue) // Player 1
DrawCrosshair(x[0], y[0], 1.0f, 0.0f, 0.0f);
if ((showCrosshairs & 1) && !Inputs->trigger[1]->offscreenValue) // Player 2
DrawCrosshair(x[1], y[1], 0.0f, 1.0f, 0.0f);
glEnd();
}
/******************************************************************************
Main Program Loop
******************************************************************************/
@ -589,7 +662,8 @@ int Supermodel(const char *zipFile, CInputs *Inputs, CINIFile *CmdLine)
CRender3D *Render3D = new CRender3D();
unsigned prevFPSTicks, currentFPSTicks, currentTicks, targetTicks, startTicks;
unsigned fpsFramesElapsed, framesElapsed;
BOOL showCursor = FALSE; // show cursor in full screen mode?
unsigned showCrosshairs = 0; // bit 1: player 1 crosshair, bit 0: player 2
bool gameHasLightguns = false;
BOOL quit = 0;
BOOL paused = 0;
@ -621,8 +695,14 @@ int Supermodel(const char *zipFile, CInputs *Inputs, CINIFile *CmdLine)
if (OKAY != OpenAudio())
return 1;
// Hide mouse if fullscreen
// Hide mouse if fullscreen, enable crosshairs for gun games
Inputs->GetInputSystem()->SetMouseVisibility(!g_Config.fullScreen);
gameHasLightguns = !!(Model3->GetGameInfo()->inputFlags & (GAME_INPUT_GUN1|GAME_INPUT_GUN2));
if (g_Config.fullScreen)
{
if (gameHasLightguns)
showCrosshairs = 3;
}
// Attach the inputs to the emulator
Model3->AttachInputs(Inputs);
@ -660,6 +740,9 @@ int Supermodel(const char *zipFile, CInputs *Inputs, CINIFile *CmdLine)
// If not, run one frame
Model3->RunFrame();
// Show crosshairs for light gun games
UpdateCrosshairs(Inputs, showCrosshairs);
// Swap the buffers
SDL_GL_SwapBuffers();
}
@ -699,7 +782,7 @@ int Supermodel(const char *zipFile, CInputs *Inputs, CINIFile *CmdLine)
Debugger->Reset();
#endif // SUPERMODEL_DEBUGGER
printf("Model 3 reset.\n");
puts("Model 3 reset.");
}
else if (Inputs->uiPause->Pressed())
{
@ -734,17 +817,23 @@ int Supermodel(const char *zipFile, CInputs *Inputs, CINIFile *CmdLine)
// Dump input states
Inputs->DumpState(Model3->GetGameInfo());
}
else if (Inputs->uiToggleCursor->Pressed() && g_Config.fullScreen)
else if (Inputs->uiSelectCrosshairs->Pressed() && gameHasLightguns)
{
// Toggle cursor in full screen mode
showCursor = !showCursor;
Inputs->GetInputSystem()->SetMouseVisibility(!!showCursor);
// Count downwards to get this sequence: both, player 1, player 2, none
showCrosshairs--;
switch ((showCrosshairs&3))
{
case 0: puts("Crosshairs disabled."); break;
case 3: puts("Crosshairs enabled."); break;
case 2: puts("Showing Player 1 crosshair only."); break;
case 1: puts("Showing Player 2 crosshair only."); break;
}
}
else if (Inputs->uiClearNVRAM->Pressed())
{
// Clear NVRAM
Model3->ClearNVRAM();
printf("NVRAM cleared.\n");
puts("NVRAM cleared.");
}
else if (Inputs->uiToggleFrLimit->Pressed())
{
@ -928,8 +1017,7 @@ static int DisassembleCROM(const char *zipFile, UINT32 addr, unsigned n)
static void Title(void)
{
puts("Supermodel: A Sega Model 3 Arcade Emulator (Version "SUPERMODEL_VERSION")");
puts("Copyright (C) 2011 by Bart Trzynadlowski");
puts("");
puts("Copyright (C) 2011 by Bart Trzynadlowski\n");
}
// Print usage information
@ -965,7 +1053,9 @@ static void Help(void)
puts(" -music-volume=<v> Set volume of MPEG music in % [Default: 100]");
puts("");
puts("Input Options:");
#ifdef SUPERMODEL_WIN32
puts(" -input-system=<s> Set input system [Default: SDL]");
#endif
puts(" -print-inputs Prints current input configuration");
puts(" -config-inputs Configure inputs for keyboards, mice, and joysticks");
puts("");
@ -1142,6 +1232,7 @@ int main(int argc, char **argv)
else
CmdLine.Set("Global", "FragmentShader", &argv[i][13]);
}
#ifdef SUPERMODEL_WIN32
else if (!strncmp(argv[i],"-input-system=", 14))
{
if (argv[i][14] == '\0')
@ -1149,6 +1240,7 @@ int main(int argc, char **argv)
else
CmdLine.Set("Global", "InputSystem", &argv[i][14]);
}
#endif
else if (!strcmp(argv[i],"-print-inputs"))
cmdPrintInputs = true;
else if (!strcmp(argv[i],"-config-inputs"))
@ -1172,7 +1264,7 @@ int main(int argc, char **argv)
return 0;
}
else if (argv[i][0] == '-')
ErrorLog("Ignoring invalid option: %s.", argv[i]);
ErrorLog("Ignoring unrecognized option: %s.", argv[i]);
else
{
if (fileIdx) // already specified a file