Skip to content

Commit

Permalink
Add lightgun crosshair support. Fix #114
Browse files Browse the repository at this point in the history
  • Loading branch information
drhelius committed Jan 5, 2025
1 parent e0763fb commit 8b60fed
Show file tree
Hide file tree
Showing 12 changed files with 259 additions and 7 deletions.
6 changes: 6 additions & 0 deletions platforms/desktop-shared/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,9 @@ void config_read(void)
config_emulator.window_height = read_int("Emulator", "WindowHeight", 503);
config_emulator.status_messages = read_bool("Emulator", "StatusMessages", false);
config_emulator.light_phaser = read_bool("Emulator", "LightPhaser", false);
config_emulator.light_phaser_crosshair = read_bool("Emulator", "LightPhaserCrosshair", false);
config_emulator.light_phaser_crosshair_shape = read_int("Emulator", "LightPhaserCrosshairShape", 0);
config_emulator.light_phaser_crosshair_color = read_int("Emulator", "LightPhaserCrosshairColor", 0);
config_emulator.paddle_control = read_bool("Emulator", "PaddleControl", false);
config_emulator.paddle_sensitivity = read_int("Emulator", "PaddleSensitivity", 5);

Expand Down Expand Up @@ -319,6 +322,9 @@ void config_write(void)
write_int("Emulator", "WindowHeight", config_emulator.window_height);
write_bool("Emulator", "StatusMessages", config_emulator.status_messages);
write_bool("Emulator", "LightPhaser", config_emulator.light_phaser);
write_bool("Emulator", "LightPhaserCrosshair", config_emulator.light_phaser_crosshair);
write_int("Emulator", "LightPhaserCrosshairShape", config_emulator.light_phaser_crosshair_shape);
write_int("Emulator", "LightPhaserCrosshairColor", config_emulator.light_phaser_crosshair_color);
write_bool("Emulator", "PaddleControl", config_emulator.paddle_control);
write_int("Emulator", "PaddleSensitivity", config_emulator.paddle_sensitivity);

Expand Down
3 changes: 3 additions & 0 deletions platforms/desktop-shared/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ struct config_Emulator
int window_height = 503;
bool status_messages = false;
bool light_phaser = false;
bool light_phaser_crosshair = false;
int light_phaser_crosshair_shape = 0;
int light_phaser_crosshair_color = 0;
bool paddle_control = false;
int paddle_sensitivity = 5;
bool capture_mouse = false;
Expand Down
5 changes: 5 additions & 0 deletions platforms/desktop-shared/emu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ void emu_enable_phaser(bool enable)
gearsystem->EnablePhaser(enable);
}

void emu_enable_phaser_crosshair(bool enable, int shape, int color)
{
gearsystem->EnablePhaserCrosshair(enable, (Video::LightPhaserCrosshairShape)shape, (Video::LightPhaserCrosshairColor)color);
}

void emu_set_paddle(float x)
{
gearsystem->SetPaddle(x);
Expand Down
1 change: 1 addition & 0 deletions platforms/desktop-shared/emu.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ EXTERN void emu_key_pressed(GS_Joypads pad, GS_Keys key);
EXTERN void emu_key_released(GS_Joypads pad, GS_Keys key);
EXTERN void emu_set_phaser(int x, int y);
EXTERN void emu_enable_phaser(bool enable);
EXTERN void emu_enable_phaser_crosshair(bool enable, int shape, int color);
EXTERN void emu_set_paddle(float x);
EXTERN void emu_enable_paddle(bool enable);
EXTERN void emu_pause(void);
Expand Down
43 changes: 38 additions & 5 deletions platforms/desktop-shared/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ void gui_init(void)
emu_set_hide_left_bar(config_video.hide_left_bar);
emu_disable_ym2413(config_audio.ym2413 == 1);
emu_enable_phaser(config_emulator.light_phaser);
emu_enable_phaser_crosshair(config_emulator.light_phaser_crosshair, config_emulator.light_phaser_crosshair_shape, config_emulator.light_phaser_crosshair_color);
emu_enable_paddle(config_emulator.paddle_control);
}

Expand Down Expand Up @@ -935,15 +936,47 @@ static void main_menu(void)

ImGui::Separator();

if (ImGui::MenuItem("Enable Light Phaser", "", &config_emulator.light_phaser))
if (ImGui::BeginMenu("Light Phaser"))
{
emu_enable_phaser(config_emulator.light_phaser);
if (ImGui::MenuItem("Enable Light Phaser", "", &config_emulator.light_phaser))
{
emu_enable_phaser(config_emulator.light_phaser);

if (config_emulator.light_phaser && config_emulator.paddle_control)
{
config_emulator.paddle_control = false;
emu_enable_paddle(false);
}
}

if (config_emulator.light_phaser && config_emulator.paddle_control)
if (ImGui::MenuItem("Enable Crosshair", "", &config_emulator.light_phaser_crosshair))
{
config_emulator.paddle_control = false;
emu_enable_paddle(false);
emu_enable_phaser_crosshair(config_emulator.light_phaser_crosshair, config_emulator.light_phaser_crosshair_shape, config_emulator.light_phaser_crosshair_color);
}

if (ImGui::BeginMenu("Crosshair Shape"))
{
ImGui::PushItemWidth(100.0f);
if (ImGui::Combo("##crosshair_shape", &config_emulator.light_phaser_crosshair_shape, "Cross\0Square\0\0"))
{
emu_enable_phaser_crosshair(config_emulator.light_phaser_crosshair, config_emulator.light_phaser_crosshair_shape, config_emulator.light_phaser_crosshair_color);
}
ImGui::PopItemWidth();
ImGui::EndMenu();
}

if (ImGui::BeginMenu("Crosshair Color"))
{
ImGui::PushItemWidth(100.0f);
if (ImGui::Combo("##crosshair_color", &config_emulator.light_phaser_crosshair_color, "White\0Black\0Red\0Green\0Blue\0Yellow\0Magenta\0Cyan\0\0"))
{
emu_enable_phaser_crosshair(config_emulator.light_phaser_crosshair, config_emulator.light_phaser_crosshair_shape, config_emulator.light_phaser_crosshair_color);
}
ImGui::PopItemWidth();
ImGui::EndMenu();
}

ImGui::EndMenu();
}

if (ImGui::BeginMenu("Paddle Control"))
Expand Down
53 changes: 53 additions & 0 deletions platforms/libretro/libretro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ static int audio_sample_count = 0;
static unsigned input_device[2];
static bool allow_up_down = false;
static bool lightgun_touchscreen = false;
static bool lightgun_crosshair = false;
static Video::LightPhaserCrosshairShape lightgun_crosshair_shape = Video::LightPhaserCrosshairCross;
static Video::LightPhaserCrosshairColor lightgun_crosshair_color = Video::LightPhaserCrosshairWhite;
static int paddle_sensitivity = 0;
static bool bootrom_sms = false;
static bool bootrom_gg = false;
Expand Down Expand Up @@ -600,6 +603,9 @@ static void set_variabless(void)
{ "gearsystem_glasses", "3D Glasses; Both Eyes / OFF|Left Eye|Right Eye" },
{ "gearsystem_up_down_allowed", "Allow Up+Down / Left+Right; Disabled|Enabled" },
{ "gearsystem_lightgun_input", "Light Gun Input; Light Gun|Touchscreen" },
{ "gearsystem_lightgun_crosshair", "Light Gun Crosshair; Disabled|Enabled" },
{ "gearsystem_lightgun_shape", "Light Gun Crosshair Shape; Cross|Square" },
{ "gearsystem_lightgun_color", "Light Gun Crosshair Color; White|Black|Red|Green|Blue|Yellow|Magenta|Cyan" },
{ "gearsystem_paddle_sensitivity", "Paddle Sensitivity; 1|2|3|4|5|6|7|8|9|10|11|12|13|14|15" },

{ NULL }
Expand Down Expand Up @@ -634,6 +640,53 @@ static void check_variables(void)
lightgun_touchscreen = false;
}

var.key = "gearsystem_lightgun_crosshair";
var.value = NULL;

if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (strcmp(var.value, "Enabled") == 0)
lightgun_crosshair = true;
else
lightgun_crosshair = false;
}

var.key = "gearsystem_lightgun_shape";
var.value = NULL;

if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (strcmp(var.value, "Cross") == 0)
lightgun_crosshair_shape = Video::LightPhaserCrosshairCross;
else
lightgun_crosshair_shape = Video::LightPhaserCrosshairSquare;
}

var.key = "gearsystem_lightgun_color";
var.value = NULL;

if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (strcmp(var.value, "White") == 0)
lightgun_crosshair_color = Video::LightPhaserCrosshairWhite;
else if (strcmp(var.value, "Black") == 0)
lightgun_crosshair_color = Video::LightPhaserCrosshairBlack;
else if (strcmp(var.value, "Red") == 0)
lightgun_crosshair_color = Video::LightPhaserCrosshairRed;
else if (strcmp(var.value, "Green") == 0)
lightgun_crosshair_color = Video::LightPhaserCrosshairGreen;
else if (strcmp(var.value, "Blue") == 0)
lightgun_crosshair_color = Video::LightPhaserCrosshairBlue;
else if (strcmp(var.value, "Yellow") == 0)
lightgun_crosshair_color = Video::LightPhaserCrosshairYellow;
else if (strcmp(var.value, "Magenta") == 0)
lightgun_crosshair_color = Video::LightPhaserCrosshairMagenta;
else if (strcmp(var.value, "Cyan") == 0)
lightgun_crosshair_color = Video::LightPhaserCrosshairCyan;
}

core->EnablePhaserCrosshair(lightgun_crosshair, lightgun_crosshair_shape, lightgun_crosshair_color);

var.key = "gearsystem_paddle_sensitivity";
var.value = NULL;

Expand Down
12 changes: 11 additions & 1 deletion src/GearsystemCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include "Memory.h"
#include "Processor.h"
#include "Audio.h"
#include "Video.h"
#include "Input.h"
#include "Cartridge.h"
#include "MemoryRule.h"
Expand Down Expand Up @@ -383,6 +382,11 @@ void GearsystemCore::EnablePhaser(bool enable)
m_pInput->EnablePhaser(enable);
}

void GearsystemCore::EnablePhaserCrosshair(bool enable, Video::LightPhaserCrosshairShape shape, Video::LightPhaserCrosshairColor color)
{
m_pVideo->SetLightPhaserCrosshair(enable, shape, color);
}

void GearsystemCore::SetPaddle(float x)
{
m_pInput->SetPaddle(x);
Expand Down Expand Up @@ -1058,6 +1062,12 @@ void GearsystemCore::Reset()

void GearsystemCore::RenderFrameBuffer(u8* finalFrameBuffer)
{
if (m_pInput->IsPhaserEnabled())
{
Input::stPhaser* phaser = m_pInput->GetPhaser();
m_pVideo->DrawPhaserCrosshair(phaser->x, phaser->y);
}

if (m_GlassesConfig != GearsystemCore::GlassesBothEyes)
{
bool left = IsSetBit(m_pInput->GetGlassesRegistry(), 0);
Expand Down
3 changes: 2 additions & 1 deletion src/GearsystemCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@

#include "definitions.h"
#include "Cartridge.h"
#include "Video.h"

class Memory;
class Processor;
class Audio;
class Video;
class Input;
class SegaMemoryRule;
class CodemastersMemoryRule;
Expand Down Expand Up @@ -76,6 +76,7 @@ class GearsystemCore
void KeyReleased(GS_Joypads joypad, GS_Keys key);
void SetPhaser(int x, int y);
void EnablePhaser(bool enable);
void EnablePhaserCrosshair(bool enable, Video::LightPhaserCrosshairShape shape, Video::LightPhaserCrosshairColor color);
void SetPaddle(float x);
void EnablePaddle(bool enable);
void Pause(bool paused);
Expand Down
5 changes: 5 additions & 0 deletions src/Input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ void Input::SetPhaser(int x, int y)
m_Phaser.y = y;
}

Input::stPhaser* Input::GetPhaser()
{
return &m_Phaser;
}

bool Input::IsPhaserEnabled()
{
return m_bPhaser;
Expand Down
1 change: 1 addition & 0 deletions src/Input.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class Input
void KeyReleased(GS_Joypads joypad, GS_Keys key);
void EnablePhaser(bool enable);
void SetPhaser(int x, int y);
stPhaser* GetPhaser();
bool IsPhaserEnabled();
void EnablePaddle(bool enable);
void SetPaddle(float x);
Expand Down
111 changes: 111 additions & 0 deletions src/Video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ Video::Video(Memory* pMemory, Processor* pProcessor, Cartridge* pCartridge)
m_Overscan = OverscanDisabled;
m_HideLeftBar = HideLeftBarNo;
m_iHideLeftBarOffset = 0;
m_bLightPhaserCrosshair = false;
m_LightPhaserCrosshairShape = LightPhaserCrosshairCross;
m_LightPhaserCrosshairColor = LightPhaserCrosshairWhite;
}

Video::~Video()
Expand Down Expand Up @@ -1225,6 +1228,114 @@ bool Video::IsPhaserDetected()
return m_Phaser.detected;
}

void Video::DrawPhaserCrosshair(int x, int y)
{
if (!m_bLightPhaserCrosshair || m_bGameGear)
return;

const int size = 3;
const int scr_width = m_iScreenWidth;
const int scr_height = m_bExtendedMode224 ? 224 : 192;

if (x < 0 || x >= scr_width || y < 0 || y >= scr_height)
return;

u16 color = 0xFFFF;

switch (m_LightPhaserCrosshairColor)
{
case LightPhaserCrosshairWhite:
color = 0b111111;
break;
case LightPhaserCrosshairBlack:
color = 0b000000;
break;
case LightPhaserCrosshairRed:
color = 0b000011;
break;
case LightPhaserCrosshairGreen:
color = 0b001100;
break;
case LightPhaserCrosshairBlue:
color = 0b110000;
break;
case LightPhaserCrosshairYellow:
color = 0b001111;
break;
case LightPhaserCrosshairMagenta:
color = 0b110011;
break;
case LightPhaserCrosshairCyan:
color = 0b111100;
break;
}

switch (m_LightPhaserCrosshairShape)
{
case LightPhaserCrosshairCross:
for (int i = -size; i <= size; ++i)
{
if (i == 0) continue;
int pixel_x = x + i;
if (pixel_x >= 0 && pixel_x < scr_width)
{
int pixel = (y * scr_width) + pixel_x;
if (pixel >= 0 && pixel < scr_width * scr_height)
{
m_pFrameBuffer[pixel] = color;
}
}
}
for (int i = -size; i <= size; ++i)
{
if (i == 0) continue;
int pixel = ((y + i) * scr_width) + x;
if (pixel >= 0 && pixel < scr_width * scr_height)
{
m_pFrameBuffer[pixel] = color;
}
}
break;

case LightPhaserCrosshairSquare:
for (int i = -size; i <= size; ++i)
{
for (int j = -size; j <= size; ++j)
{
if ((abs(i) == size || abs(j) == size) && !(i == 0 || j == 0))
{
int pixel_x = x + i;
int pixel_y = y + j;
if (pixel_x >= 0 && pixel_x < scr_width && pixel_y >= 0 && pixel_y < scr_height)
{
int pixel = (pixel_y * scr_width) + pixel_x;
if (pixel >= 0 && pixel < scr_width * scr_height)
{
m_pFrameBuffer[pixel] = color;
}
}
}
}
}
if (x >= 0 && x < scr_width && y >= 0 && y < scr_height)
{
int pixel = (y * scr_width) + x;
if (pixel >= 0 && pixel < scr_width * scr_height)
{
m_pFrameBuffer[pixel] = color;
}
}
break;
}
}

void Video::SetLightPhaserCrosshair(bool enable, LightPhaserCrosshairShape shape, LightPhaserCrosshairColor color)
{
m_bLightPhaserCrosshair = enable;
m_LightPhaserCrosshairShape = shape;
m_LightPhaserCrosshairColor = color;
}

void Video::InitPalettes(const u8* src, u16* dest_565_rgb, u16* dest_555_rgb, u16* dest_565_bgr, u16* dest_555_bgr)
{
for (int i=0,j=0; i<16; i++,j+=3)
Expand Down
Loading

0 comments on commit 8b60fed

Please sign in to comment.