Crosshair refactor

-add a new separate class for crosshair
-crosshair coordinates are calculated by matrix instead of recreating every object at correct coordinates
-add ability to scale crosshair by dpi
-add ability to use bitmap crosshair (located in ./Media/). 32bits bmp format + alpha
-cmd line "-bitmapcrosshair" or "-vectorcrosshair" and/or BitmapCrosshair=0|1 in config file
-these changes are only for lost world game with Crosshairs=1|2|3

don't forget to copy the 2 crosshair images in Supermodel/Media folder
This commit is contained in:
CapitaineSheridan 2022-12-23 17:36:26 +01:00 committed by trzy
parent 0cc1b37f95
commit 1b066fe4b3
13 changed files with 418 additions and 130 deletions

View file

@ -149,6 +149,7 @@ SRC_FILES = \
Src/Inputs/InputTypes.cpp \ Src/Inputs/InputTypes.cpp \
Src/Inputs/MultiInputSource.cpp \ Src/Inputs/MultiInputSource.cpp \
Src/OSD/SDL/SDLInputSystem.cpp \ Src/OSD/SDL/SDLInputSystem.cpp \
Src/OSD/SDL/Crosshair.cpp \
Src/OSD/Outputs.cpp \ Src/OSD/Outputs.cpp \
Src/Sound/MPEG/MpegAudio.cpp \ Src/Sound/MPEG/MpegAudio.cpp \
Src/Model3/Crypto.cpp \ Src/Model3/Crypto.cpp \

6
Media/DIR.txt Normal file
View file

@ -0,0 +1,6 @@
Crosshairs images needs to be placed in here.
32bits bmp format + alpha
size multiple of 2
p1crosshair.bmp
p2crosshair.bmp

BIN
Media/p1crosshair.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

BIN
Media/p2crosshair.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

View file

@ -32,7 +32,7 @@
namespace FileSystemPath namespace FileSystemPath
{ {
enum PathType { Analysis, Config, Log, NVRAM, Saves, Screenshots }; // Filesystem path types enum PathType { Analysis, Config, Log, NVRAM, Saves, Screenshots, Media }; // Filesystem path types
bool PathExists(std::string fileSystemPath); // Checks if a directory exists (returns true if exists, false if it doesn't) bool PathExists(std::string fileSystemPath); // Checks if a directory exists (returns true if exists, false if it doesn't)
std::string GetPath(PathType pathType); // Generates a path to be used by Supermodel files std::string GetPath(PathType pathType); // Generates a path to be used by Supermodel files
} }

View file

@ -41,6 +41,8 @@ namespace FileSystemPath
return "Saves/"; return "Saves/";
case Screenshots: case Screenshots:
return ""; return "";
case Media:
return "Media/";
} }
} }
} }

244
Src/OSD/SDL/Crosshair.cpp Normal file
View file

@ -0,0 +1,244 @@
/**
** Supermodel
** A Sega Model 3 Arcade Emulator.
** Copyright 2003-2022 The Supermodel Team
**
** 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/>.
**/
#include "Crosshair.h"
#include "Supermodel.h"
#include "Graphics/New3D/New3D.h"
#include "OSD/FileSystemPath.h"
#include "SDLIncludes.h"
#include <GL/glew.h>
#include <vector>
bool CCrosshair::init()
{
const std::string P1CrosshairFile = Util::Format() << FileSystemPath::GetPath(FileSystemPath::Media) << "p1crosshair.bmp";
const std::string P2CrosshairFile = Util::Format() << FileSystemPath::GetPath(FileSystemPath::Media) << "p2crosshair.bmp";
IsBitmapCrosshair = m_config["BitmapCrosshair"].ValueAs<bool>();
xRes = m_config["XResolution"].ValueAs<unsigned>();
yRes = m_config["YResolution"].ValueAs<unsigned>();
a = (float)xRes / (float)yRes;
SDL_Surface* SurfaceCrosshairP1 = SDL_LoadBMP(P1CrosshairFile.c_str());
SDL_Surface* SurfaceCrosshairP2 = SDL_LoadBMP(P2CrosshairFile.c_str());
if (SurfaceCrosshairP1 == NULL || SurfaceCrosshairP2 == NULL)
return FAIL;
P1CrosshairW = SurfaceCrosshairP1->w;
P1CrosshairH = SurfaceCrosshairP1->h;
P2CrosshairW = SurfaceCrosshairP2->w;
P2CrosshairH = SurfaceCrosshairP2->h;
glGenTextures(2, CrosshairtxID);
glBindTexture(GL_TEXTURE_2D, CrosshairtxID[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, P1CrosshairW, P1CrosshairH, 0, GL_BGRA, GL_UNSIGNED_BYTE, SurfaceCrosshairP1->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, CrosshairtxID[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, P1CrosshairW, P1CrosshairH, 0, GL_BGRA, GL_UNSIGNED_BYTE, SurfaceCrosshairP2->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
SDL_FreeSurface(SurfaceCrosshairP1);
SDL_FreeSurface(SurfaceCrosshairP2);
// Get DPI
SDL_GetDisplayDPI(0, &diagdpi, &hdpi, &vdpi);
dpiMultiplicator = hdpi / standardDpi; // note : on linux VM diagdpi returns 0
// 3d obj
UVCoord.emplace_back(0.0f, 0.0f);
UVCoord.emplace_back(1.0f, 0.0f);
UVCoord.emplace_back(1.0f, 1.0f);
UVCoord.emplace_back(0.0f, 0.0f);
UVCoord.emplace_back(1.0f, 1.0f);
UVCoord.emplace_back(0.0f, 1.0f);
if (!IsBitmapCrosshair)
{
verts.emplace_back(0.0f, dist); // bottom triangle
verts.emplace_back(base / 2.0f, (dist + height) * a);
verts.emplace_back(-base / 2.0f, (dist + height) * a);
verts.emplace_back(0.0f, -dist); // top triangle
verts.emplace_back(-base / 2.0f, -(dist + height) * a);
verts.emplace_back(base / 2.0f, -(dist + height) * a);
verts.emplace_back(-dist, 0.0f); // left triangle
verts.emplace_back(-dist - height, (base / 2.0f) * a);
verts.emplace_back(-dist - height, -(base / 2.0f) * a);
verts.emplace_back(dist, 0.0f); // right triangle
verts.emplace_back(dist + height, -(base / 2.0f) * a);
verts.emplace_back(dist + height, (base / 2.0f) * a);
}
else
{
verts.emplace_back(-squareSize / 2.0f, -squareSize / 2.0f * a);
verts.emplace_back(squareSize / 2.0f, -squareSize / 2.0f * a);
verts.emplace_back(squareSize / 2.0f, squareSize / 2.0f * a);
verts.emplace_back(-squareSize / 2.0f, -squareSize / 2.0f * a);
verts.emplace_back(squareSize / 2.0f, squareSize / 2.0f * a);
verts.emplace_back(-squareSize / 2.0f, squareSize / 2.0f * a);
}
vertexShader = R"glsl(
#version 410 core
uniform mat4 mvp;
layout(location = 0) in vec3 inVertices;
layout(location = 1) in vec2 vertexUV;
out vec2 UV;
void main(void)
{
gl_Position = mvp * vec4(inVertices,1.0);
UV = vertexUV;
}
)glsl";
fragmentShader = R"glsl(
#version 410 core
uniform vec4 colour;
uniform sampler2D CrosshairTexture;
uniform bool isBitmap;
out vec4 fragColour;
in vec2 UV;
void main(void)
{
if (!isBitmap)
fragColour = colour;
else
fragColour = colour * texture(CrosshairTexture, UV);
}
)glsl";
m_shader.LoadShaders(vertexShader, fragmentShader);
m_shader.GetUniformLocationMap("mvp");
m_shader.GetUniformLocationMap("CrosshairTexture");
m_shader.GetUniformLocationMap("colour");
m_shader.GetUniformLocationMap("isBitmap");
m_vbo.Create(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(BasicVertex) * (MaxVerts));
m_vbo.Bind(true);
m_textvbo.Create(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(UVCoords) * (int)UVCoord.size());
m_textvbo.Bind(true);
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
m_vbo.Bind(true);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(BasicVertex), 0);
m_vbo.Bind(false);
m_textvbo.Bind(true);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(UVCoords), 0);
m_textvbo.Bind(false);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindVertexArray(0);
return OKAY;
}
void CCrosshair::DrawCrosshair(New3D::Mat4 matrix, float x, float y, float r, float g, float b)
{
int count = (int)verts.size();
if (count > MaxVerts) {
count = MaxVerts; // maybe we could error out somehow
}
m_shader.EnableShader();
matrix.Translate(x, y, 0);
matrix.Scale(dpiMultiplicator, dpiMultiplicator, 0);
// update uniform memory
glUniformMatrix4fv(m_shader.uniformLocMap["mvp"], 1, GL_FALSE, matrix);
glUniform4f(m_shader.uniformLocMap["colour"], r, g, b, 1.0f);
glUniform1i(m_shader.uniformLocMap["isBitmap"], false);
// update vbo mem
m_vbo.Bind(true);
m_vbo.BufferSubData(0, count * sizeof(BasicVertex), verts.data());
glBindVertexArray(m_vao);
glDrawArrays(GL_TRIANGLES, 0, count);
glBindVertexArray(0);
m_shader.DisableShader();
}
void CCrosshair::DrawBitmapCrosshair(New3D::Mat4 matrix, float x, float y, int TextureNum)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, CrosshairtxID[TextureNum]);
int count = (int)verts.size();
if (count > MaxVerts) {
count = MaxVerts; // maybe we could error out somehow
}
m_TextureCoordsCount = (int)UVCoord.size();
m_shader.EnableShader();
matrix.Translate(x, y, 0);
matrix.Scale(dpiMultiplicator * ScaleBitmap, dpiMultiplicator * ScaleBitmap, 0);
// update uniform memory
glUniformMatrix4fv(m_shader.uniformLocMap["mvp"], 1, GL_FALSE, matrix);
glUniform1i(m_shader.uniformLocMap["CrosshairTexture"], 0); // 0 or 1 or GL_TEXTURE0 GL_TEXTURE1
glUniform4f(m_shader.uniformLocMap["colour"], 1.0f, 1.0f, 1.0f, 1.0f);
glUniform1i(m_shader.uniformLocMap["isBitmap"], true);
// update vbo mem
m_vbo.Bind(true);
m_vbo.BufferSubData(0, count * sizeof(BasicVertex), verts.data());
m_vbo.Bind(false);
m_textvbo.Bind(true);
m_textvbo.BufferSubData(0, m_TextureCoordsCount * sizeof(UVCoords), UVCoord.data());
m_textvbo.Bind(false);
glBindVertexArray(m_vao);
glDrawArrays(GL_TRIANGLES, 0, count);
glBindVertexArray(0);
m_shader.DisableShader();
}
CCrosshair::CCrosshair(const Util::Config::Node& config) : m_config(config),xRes(0),yRes(0)
{
vertexShader = nullptr;
fragmentShader = nullptr;
}
CCrosshair::~CCrosshair()
{
}

80
Src/OSD/SDL/Crosshair.h Normal file
View file

@ -0,0 +1,80 @@
/**
** Supermodel
** A Sega Model 3 Arcade Emulator.
** Copyright 2003-2022 The Supermodel Team
**
** 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/>.
**/
#ifndef INCLUDED_CROSSHAIR_H
#define INCLUDED_CROSSHAIR_H
#include "Supermodel.h"
#include "Graphics/New3D/New3D.h"
class CCrosshair
{
private:
const Util::Config::Node& m_config;
bool IsBitmapCrosshair=false;
GLuint CrosshairtxID[2] = { 0 };
int P1CrosshairW = 0, P1CrosshairH = 0, P2CrosshairW = 0, P2CrosshairH = 0;
float diagdpi = 0.0f, hdpi = 0.0f, vdpi = 0.0f;
unsigned int xRes=0;
unsigned int yRes=0;
const float base = 0.01f, height = 0.02f; // geometric parameters of each triangle
const float dist = 0.004f; // distance of triangle tip from center
float a = 0.0f; // aspect ratio (to square the crosshair)
const float squareSize = 1.0f;
const float standardDpi = 96.0f; // normal dpi for usual monitor (full hd)
float dpiMultiplicator = 0.0f;
const float ScaleBitmap = 0.1f;
struct BasicVertex
{
BasicVertex(float x, float y, float z) : x(x), y(y), z(z) {}
BasicVertex(float x, float y) : x(x), y(y), z(0.0f) {}
float x, y, z;
};
struct UVCoords
{
UVCoords(float x, float y) : x(x), y(y) {}
float x, y;
};
std::vector<BasicVertex> verts;
std::vector<UVCoords> UVCoord;
GLSLShader m_shader;
VBO m_vbo;
VBO m_textvbo;
GLuint m_vao = 0;
int m_TextureCoordsCount = 0;
const char* vertexShader;
const char* fragmentShader;
const int MaxVerts = 1024; // per draw call
public:
CCrosshair(const Util::Config::Node& config);
~CCrosshair();
bool init();
void DrawCrosshair(New3D::Mat4 matrix, float x, float y, float r, float g, float b);
void DrawBitmapCrosshair(New3D::Mat4 matrix, float x, float y, int TextureNum);
};
#endif

View file

@ -81,6 +81,7 @@
#include <iostream> #include <iostream>
#include "Util/BMPFile.h" #include "Util/BMPFile.h"
#include "Crosshair.h"
/****************************************************************************** /******************************************************************************
Global Run-time Config Global Run-time Config
@ -105,6 +106,12 @@ static unsigned xOffset, yOffset; // offset of renderer output within Open
static unsigned xRes, yRes; // renderer output resolution (can be smaller than GL viewport) static unsigned xRes, yRes; // renderer output resolution (can be smaller than GL viewport)
static unsigned totalXRes, totalYRes; // total resolution (the whole GL viewport) static unsigned totalXRes, totalYRes; // total resolution (the whole GL viewport)
/*
* Crosshair stuff
*/
static bool IsBitmapCrosshair = false;
CCrosshair* Crosshair = nullptr;
static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *xResPtr, unsigned *yResPtr, unsigned *totalXResPtr, unsigned *totalYResPtr, bool keepAspectRatio) static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *xResPtr, unsigned *yResPtr, unsigned *totalXResPtr, unsigned *totalYResPtr, bool keepAspectRatio)
{ {
// What resolution did we actually get? // What resolution did we actually get?
@ -781,132 +788,12 @@ static void LoadNVRAM(IEmulator *Model3)
Currently, only does crosshairs for light gun games. Currently, only does crosshairs for light gun games.
******************************************************************************/ ******************************************************************************/
struct BasicDraw
{
public:
struct BasicVertex
{
BasicVertex(float x, float y, float z) : x(x), y(y), z(z) {}
BasicVertex(float x, float y) : x(x), y(y), z(0.f) {}
float x, y, z;
};
const int MaxVerts = 1024; // per draw call
void Draw(GLenum mode, const float mvpMatrix[16], const BasicVertex* vertices, int count, float r, float g, float b, float a)
{
if (count > MaxVerts) {
count = MaxVerts; // maybe we could error out somehow
}
if (!m_initialised) {
Setup();
}
m_shader.EnableShader();
// update uniform memory
glUniformMatrix4fv(m_shader.uniformLocMap["mvp"], 1, GL_FALSE, mvpMatrix);
glUniform4f(m_shader.uniformLocMap["colour"], r, g, b, a);
// update vbo mem
m_vbo.Bind(true);
m_vbo.BufferSubData(0, count * sizeof(BasicVertex), vertices);
glBindVertexArray(m_vao);
glDrawArrays(mode, 0, count);
glBindVertexArray(0);
m_shader.DisableShader();
}
private:
void Setup()
{
const char* vertexShader = R"glsl(
#version 410 core
uniform mat4 mvp;
layout(location = 0) in vec3 inVertices;
void main(void)
{
gl_Position = mvp * vec4(inVertices,1.0);
}
)glsl";
const char* fragmentShader = R"glsl(
#version 410 core
uniform vec4 colour;
out vec4 fragColour;
void main(void)
{
fragColour = colour;
}
)glsl";
m_shader.LoadShaders(vertexShader, fragmentShader);
m_shader.GetUniformLocationMap("mvp");
m_shader.GetUniformLocationMap("colour");
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
m_vbo.Create(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(BasicVertex) * (MaxVerts));
m_vbo.Bind(true);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(BasicVertex), 0);
glBindVertexArray(0);
m_vbo.Bind(false);
m_initialised = true;
}
GLSLShader m_shader;
VBO m_vbo;
GLuint m_vao = 0;
bool m_initialised = false;
} basicDraw;
static void GunToViewCoords(float *x, float *y) static void GunToViewCoords(float *x, float *y)
{ {
*x = (*x-150.0f)/(651.0f-150.0f); // Scale [150,651] -> [0.0,1.0] *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] *y = (*y-80.0f)/(465.0f-80.0f); // Scale [80,465] -> [0.0,1.0]
} }
static void DrawCrosshair(const float* matrix, float x, float y, float r, float g, float b)
{
float base = 0.01f, height = 0.02f; // geometric parameters of each triangle
float dist = 0.004f; // distance of triangle tip from center
float a = (float)xRes/(float)yRes; // aspect ratio (to square the crosshair)
std::vector<BasicDraw::BasicVertex> verts;
verts.emplace_back(x, y+dist); // bottom triangle
verts.emplace_back(x+base/2.0f, y+(dist+height)*a);
verts.emplace_back(x-base/2.0f, y+(dist+height)*a);
verts.emplace_back(x, y-dist); // top triangle
verts.emplace_back(x-base/2.0f, y-(dist+height)*a);
verts.emplace_back(x+base/2.0f, y-(dist+height)*a);
verts.emplace_back(x-dist, y); // left triangle
verts.emplace_back(x-dist-height, y+(base/2.0f)*a);
verts.emplace_back(x-dist-height, y-(base/2.0f)*a);
verts.emplace_back(x+dist, y); // right triangle
verts.emplace_back(x+dist+height, y-(base/2.0f)*a);
verts.emplace_back(x+dist+height, y+(base/2.0f)*a);
basicDraw.Draw(GL_TRIANGLES, matrix, verts.data(), (int)verts.size(), r, g, b, 1.0f);
}
/* /*
static void PrintGLError(GLenum error) static void PrintGLError(GLenum error)
{ {
@ -937,8 +824,18 @@ static void UpdateCrosshairs(uint32_t currentInputs, CInputs *Inputs, unsigned c
// Set up the viewport and orthogonal projection // Set up the viewport and orthogonal projection
glUseProgram(0); // no shaders glUseProgram(0); // no shaders
glViewport(xOffset, yOffset, xRes, yRes); glViewport(xOffset, yOffset, xRes, yRes);
glDisable(GL_BLEND); // no blending
glDisable(GL_DEPTH_TEST); // no Z-buffering needed glDisable(GL_DEPTH_TEST); // no Z-buffering needed
if (!IsBitmapCrosshair)
{
glDisable(GL_BLEND); // no blending
}
else
{
glEnable(GL_TEXTURE_2D); // enable texture mapping, blending and alpha chanel
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
New3D::Mat4 m; New3D::Mat4 m;
m.Ortho(0.0, 1.0, 1.0, 0.0, -1.0f, 1.0f); m.Ortho(0.0, 1.0, 1.0, 0.0, -1.0f, 1.0f);
@ -970,11 +867,30 @@ static void UpdateCrosshairs(uint32_t currentInputs, CInputs *Inputs, unsigned c
GunToViewCoords(&x[1], &y[1]); GunToViewCoords(&x[1], &y[1]);
offscreenTrigger[1] = (Inputs->trigger[1]->offscreenValue) > 0; offscreenTrigger[1] = (Inputs->trigger[1]->offscreenValue) > 0;
} }
// Draw visible crosshairs // Draw visible crosshairs
if ((crosshairs & 1) && !offscreenTrigger[0]) // Player 1 if (!IsBitmapCrosshair)
DrawCrosshair(m,x[0], y[0], 1.0f, 0.0f, 0.0f); {
if ((crosshairs & 2) && !offscreenTrigger[1]) // Player 2 if ((crosshairs & 1) && !offscreenTrigger[0]) // Player 1
DrawCrosshair(m,x[1], y[1], 0.0f, 1.0f, 0.0f); {
Crosshair->DrawCrosshair(m, x[0], y[0], 1.0f, 0.0f, 0.0f);
}
if ((crosshairs & 2) && !offscreenTrigger[1]) // Player 2
{
Crosshair->DrawCrosshair(m, x[1], y[1], 0.0f, 1.0f, 0.0f);
}
}
else
{
if ((crosshairs & 1) && !offscreenTrigger[0]) // Player 1
{
Crosshair->DrawBitmapCrosshair(m, x[0], y[0], 0);
}
if ((crosshairs & 2) && !offscreenTrigger[1]) // Player 2
{
Crosshair->DrawBitmapCrosshair(m, x[1], y[1], 1);
}
}
//PrintGLError(glGetError()); //PrintGLError(glGetError());
} }
@ -1650,6 +1566,7 @@ static Util::Config::Node DefaultConfig()
config.Set("RefreshRate", 60.0f); config.Set("RefreshRate", 60.0f);
config.Set("ShowFrameRate", false); config.Set("ShowFrameRate", false);
config.Set("Crosshairs", int(0)); config.Set("Crosshairs", int(0));
config.Set("BitmapCrosshair", false);
config.Set("FlipStereo", false); config.Set("FlipStereo", false);
#ifdef SUPERMODEL_WIN32 #ifdef SUPERMODEL_WIN32
config.Set("InputSystem", "dinput"); config.Set("InputSystem", "dinput");
@ -1735,6 +1652,8 @@ static void Help(void)
puts(" -show-fps Display frame rate in window title bar"); puts(" -show-fps Display frame rate in window title bar");
puts(" -crosshairs=<n> Crosshairs configuration for gun games:"); puts(" -crosshairs=<n> Crosshairs configuration for gun games:");
puts(" 0=none [Default], 1=P1 only, 2=P2 only, 3=P1 & P2"); puts(" 0=none [Default], 1=P1 only, 2=P2 only, 3=P1 & P2");
puts(" -vectorcrosshair Use built-in crosshair [Default]");
puts(" -bitmapcrosshair Use image (.bmp) as crosshair (only for lost world)");
puts(" -new3d New 3D engine by Ian Curtis [Default]"); puts(" -new3d New 3D engine by Ian Curtis [Default]");
puts(" -quad-rendering Enable proper quad rendering"); puts(" -quad-rendering Enable proper quad rendering");
puts(" -legacy3d Legacy 3D engine (faster but less accurate)"); puts(" -legacy3d Legacy 3D engine (faster but less accurate)");
@ -1870,6 +1789,8 @@ static ParsedCommandLine ParseCommandLine(int argc, char **argv)
{ "-no-dsb", { "EmulateDSB", false } }, { "-no-dsb", { "EmulateDSB", false } },
{ "-legacy-scsp", { "LegacySoundDSP", true } }, { "-legacy-scsp", { "LegacySoundDSP", true } },
{ "-new-scsp", { "LegacySoundDSP", false } }, { "-new-scsp", { "LegacySoundDSP", false } },
{ "-bitmapcrosshair", { "BitmapCrosshair", true } },
{ "-vectorcrosshair", { "BitmapCrosshair", false } },
#ifdef NET_BOARD #ifdef NET_BOARD
{ "-net", { "Network", true } }, { "-net", { "Network", true } },
{ "-no-net", { "Network", false } }, { "-no-net", { "Network", false } },
@ -2131,6 +2052,17 @@ int main(int argc, char **argv)
goto Exit; goto Exit;
} }
IsBitmapCrosshair = s_runtime_config["BitmapCrosshair"].ValueAs<bool>();
// Create Bitmap Crosshair
Crosshair = new CCrosshair(s_runtime_config);
if (Crosshair->init() != OKAY)
{
ErrorLog("Unable to load bitmap crosshair texture\n");
exitCode = 1;
goto Exit;
}
// Create Model 3 emulator // Create Model 3 emulator
#ifdef DEBUG #ifdef DEBUG
Model3 = s_gfxStatePath.empty() ? static_cast<IEmulator *>(new CModel3(s_runtime_config)) : static_cast<IEmulator *>(new CModel3GraphicsState(s_runtime_config, s_gfxStatePath)); Model3 = s_gfxStatePath.empty() ? static_cast<IEmulator *>(new CModel3(s_runtime_config)) : static_cast<IEmulator *>(new CModel3GraphicsState(s_runtime_config, s_gfxStatePath));
@ -2232,6 +2164,8 @@ Exit:
delete InputSystem; delete InputSystem;
if (Outputs != NULL) if (Outputs != NULL)
delete Outputs; delete Outputs;
if (Crosshair != NULL)
delete Crosshair;
DestroyGLScreen(); DestroyGLScreen();
SDL_Quit(); SDL_Quit();

View file

@ -73,6 +73,9 @@ namespace FileSystemPath
case Screenshots: case Screenshots:
strPathType = "Screenshots"; strPathType = "Screenshots";
break; break;
case Media:
strPathType = "Media/";
break;
} }
// Get user's HOME directory // Get user's HOME directory

View file

@ -41,6 +41,8 @@ namespace FileSystemPath
return "Saves/"; return "Saves/";
case Screenshots: case Screenshots:
return ""; return "";
case Media:
return "Media/";
} }
return ""; return "";

View file

@ -114,8 +114,10 @@
<Command>if not exist "$(TargetDir)Config" mkdir "$(TargetDir)Config" <Command>if not exist "$(TargetDir)Config" mkdir "$(TargetDir)Config"
if not exist "$(TargetDir)NVRAM" mkdir "$(TargetDir)NVRAM" if not exist "$(TargetDir)NVRAM" mkdir "$(TargetDir)NVRAM"
if not exist "$(TargetDir)Saves" mkdir "$(TargetDir)Saves" if not exist "$(TargetDir)Saves" mkdir "$(TargetDir)Saves"
if not exist "$(TargetDir)Media" mkdir "$(TargetDir)Media"
xcopy /D /Y "$(ProjectDir)..\Docs\*" "$(TargetDir)" xcopy /D /Y "$(ProjectDir)..\Docs\*" "$(TargetDir)"
xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"</Command> xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"
xcopy /D /Y "$(ProjectDir)..\Media\*" "$(TargetDir)Media"</Command>
</PostBuildEvent> </PostBuildEvent>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -145,8 +147,10 @@ xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"</Command>
<Command>if not exist "$(TargetDir)Config" mkdir "$(TargetDir)Config" <Command>if not exist "$(TargetDir)Config" mkdir "$(TargetDir)Config"
if not exist "$(TargetDir)NVRAM" mkdir "$(TargetDir)NVRAM" if not exist "$(TargetDir)NVRAM" mkdir "$(TargetDir)NVRAM"
if not exist "$(TargetDir)Saves" mkdir "$(TargetDir)Saves" if not exist "$(TargetDir)Saves" mkdir "$(TargetDir)Saves"
if not exist "$(TargetDir)Media" mkdir "$(TargetDir)Media"
xcopy /D /Y "$(ProjectDir)..\Docs\*" "$(TargetDir)" xcopy /D /Y "$(ProjectDir)..\Docs\*" "$(TargetDir)"
xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"</Command> xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"
xcopy /D /Y "$(ProjectDir)..\Media\*" "$(TargetDir)Media"</Command>
</PostBuildEvent> </PostBuildEvent>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -175,8 +179,10 @@ xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"</Command>
<Command>if not exist "$(TargetDir)Config" mkdir "$(TargetDir)Config" <Command>if not exist "$(TargetDir)Config" mkdir "$(TargetDir)Config"
if not exist "$(TargetDir)NVRAM" mkdir "$(TargetDir)NVRAM" if not exist "$(TargetDir)NVRAM" mkdir "$(TargetDir)NVRAM"
if not exist "$(TargetDir)Saves" mkdir "$(TargetDir)Saves" if not exist "$(TargetDir)Saves" mkdir "$(TargetDir)Saves"
if not exist "$(TargetDir)Media" mkdir "$(TargetDir)Media"
xcopy /D /Y "$(ProjectDir)..\Docs\*" "$(TargetDir)" xcopy /D /Y "$(ProjectDir)..\Docs\*" "$(TargetDir)"
xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"</Command> xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"
xcopy /D /Y "$(ProjectDir)..\Media\*" "$(TargetDir)Media"</Command>
</PostBuildEvent> </PostBuildEvent>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -209,8 +215,10 @@ xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"</Command>
<Command>if not exist "$(TargetDir)Config" mkdir "$(TargetDir)Config" <Command>if not exist "$(TargetDir)Config" mkdir "$(TargetDir)Config"
if not exist "$(TargetDir)NVRAM" mkdir "$(TargetDir)NVRAM" if not exist "$(TargetDir)NVRAM" mkdir "$(TargetDir)NVRAM"
if not exist "$(TargetDir)Saves" mkdir "$(TargetDir)Saves" if not exist "$(TargetDir)Saves" mkdir "$(TargetDir)Saves"
if not exist "$(TargetDir)Media" mkdir "$(TargetDir)Media"
xcopy /D /Y "$(ProjectDir)..\Docs\*" "$(TargetDir)" xcopy /D /Y "$(ProjectDir)..\Docs\*" "$(TargetDir)"
xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"</Command> xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"
xcopy /D /Y "$(ProjectDir)..\Media\*" "$(TargetDir)Media"</Command>
</PostBuildEvent> </PostBuildEvent>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
@ -347,6 +355,7 @@ xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"</Command>
<ClCompile Include="..\Src\OSD\Logger.cpp" /> <ClCompile Include="..\Src\OSD\Logger.cpp" />
<ClCompile Include="..\Src\OSD\Outputs.cpp" /> <ClCompile Include="..\Src\OSD\Outputs.cpp" />
<ClCompile Include="..\Src\OSD\SDL\Audio.cpp" /> <ClCompile Include="..\Src\OSD\SDL\Audio.cpp" />
<ClCompile Include="..\Src\OSD\SDL\Crosshair.cpp" />
<ClCompile Include="..\Src\OSD\SDL\Main.cpp" /> <ClCompile Include="..\Src\OSD\SDL\Main.cpp" />
<ClCompile Include="..\Src\OSD\SDL\SDLInputSystem.cpp" /> <ClCompile Include="..\Src\OSD\SDL\SDLInputSystem.cpp" />
<ClCompile Include="..\Src\OSD\SDL\Thread.cpp" /> <ClCompile Include="..\Src\OSD\SDL\Thread.cpp" />
@ -523,6 +532,7 @@ xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"</Command>
<ClInclude Include="..\Src\OSD\Audio.h" /> <ClInclude Include="..\Src\OSD\Audio.h" />
<ClInclude Include="..\Src\OSD\Logger.h" /> <ClInclude Include="..\Src\OSD\Logger.h" />
<ClInclude Include="..\Src\OSD\Outputs.h" /> <ClInclude Include="..\Src\OSD\Outputs.h" />
<ClInclude Include="..\Src\OSD\SDL\Crosshair.h" />
<ClInclude Include="..\Src\OSD\SDL\OSDConfig.h" /> <ClInclude Include="..\Src\OSD\SDL\OSDConfig.h" />
<ClInclude Include="..\Src\OSD\SDL\SDLInputSystem.h" /> <ClInclude Include="..\Src\OSD\SDL\SDLInputSystem.h" />
<ClInclude Include="..\Src\OSD\SDL\Types.h" /> <ClInclude Include="..\Src\OSD\SDL\Types.h" />

View file

@ -464,6 +464,9 @@
<ClCompile Include="..\Src\Network\SimNetBoard.cpp"> <ClCompile Include="..\Src\Network\SimNetBoard.cpp">
<Filter>Source Files\Network</Filter> <Filter>Source Files\Network</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Src\OSD\SDL\Crosshair.cpp">
<Filter>Source Files\OSD\SDL</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<MASM Include="..\Src\CPU\68K\Turbo68K\Turbo68K.asm"> <MASM Include="..\Src\CPU\68K\Turbo68K\Turbo68K.asm">
@ -841,6 +844,9 @@
<ClInclude Include="..\Src\Util\BitCast.h"> <ClInclude Include="..\Src\Util\BitCast.h">
<Filter>Header Files\Util</Filter> <Filter>Header Files\Util</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\Src\OSD\SDL\Crosshair.h">
<Filter>Header Files\OSD\SDL</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CustomBuild Include="..\Src\Debugger\ReadMe.txt"> <CustomBuild Include="..\Src\Debugger\ReadMe.txt">