diff --git a/platforms/desktop-shared/config.cpp b/platforms/desktop-shared/config.cpp index e893b4f4..9ab1d004 100644 --- a/platforms/desktop-shared/config.cpp +++ b/platforms/desktop-shared/config.cpp @@ -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); @@ -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); diff --git a/platforms/desktop-shared/config.h b/platforms/desktop-shared/config.h index 7de770ac..9ab65d5b 100644 --- a/platforms/desktop-shared/config.h +++ b/platforms/desktop-shared/config.h @@ -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; diff --git a/platforms/desktop-shared/emu.cpp b/platforms/desktop-shared/emu.cpp index 2fb332d3..9f427061 100644 --- a/platforms/desktop-shared/emu.cpp +++ b/platforms/desktop-shared/emu.cpp @@ -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); diff --git a/platforms/desktop-shared/emu.h b/platforms/desktop-shared/emu.h index 6c0af330..66675e9e 100644 --- a/platforms/desktop-shared/emu.h +++ b/platforms/desktop-shared/emu.h @@ -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); diff --git a/platforms/desktop-shared/gui.cpp b/platforms/desktop-shared/gui.cpp index fa39b765..e672f6a0 100644 --- a/platforms/desktop-shared/gui.cpp +++ b/platforms/desktop-shared/gui.cpp @@ -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); } @@ -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")) diff --git a/platforms/libretro/libretro.cpp b/platforms/libretro/libretro.cpp index d748035d..62a074e9 100644 --- a/platforms/libretro/libretro.cpp +++ b/platforms/libretro/libretro.cpp @@ -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; @@ -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 } @@ -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; diff --git a/src/GearsystemCore.cpp b/src/GearsystemCore.cpp index bfcb282b..0a874a21 100644 --- a/src/GearsystemCore.cpp +++ b/src/GearsystemCore.cpp @@ -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" @@ -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); @@ -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); diff --git a/src/GearsystemCore.h b/src/GearsystemCore.h index bcad5a5e..8ec71ee5 100644 --- a/src/GearsystemCore.h +++ b/src/GearsystemCore.h @@ -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; @@ -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); diff --git a/src/Input.cpp b/src/Input.cpp index 62b832a3..e2b56b7c 100644 --- a/src/Input.cpp +++ b/src/Input.cpp @@ -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; diff --git a/src/Input.h b/src/Input.h index 030e4a50..add1c6ca 100644 --- a/src/Input.h +++ b/src/Input.h @@ -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); diff --git a/src/Video.cpp b/src/Video.cpp index c237a554..564185f5 100644 --- a/src/Video.cpp +++ b/src/Video.cpp @@ -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() @@ -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) diff --git a/src/Video.h b/src/Video.h index 6bee748f..07d3ddc6 100644 --- a/src/Video.h +++ b/src/Video.h @@ -44,6 +44,24 @@ class Video HideLeftBarAlways }; + enum LightPhaserCrosshairShape + { + LightPhaserCrosshairCross, + LightPhaserCrosshairSquare + }; + + enum LightPhaserCrosshairColor + { + LightPhaserCrosshairWhite, + LightPhaserCrosshairBlack, + LightPhaserCrosshairRed, + LightPhaserCrosshairGreen, + LightPhaserCrosshairBlue, + LightPhaserCrosshairYellow, + LightPhaserCrosshairMagenta, + LightPhaserCrosshairCyan + }; + public: Video(Memory* pMemory, Processor* pProcessor, Cartridge* pCartridge); ~Video(); @@ -76,6 +94,8 @@ class Video int GetHideLeftBarOffset(); void SetPhaserCoordinates(int x, int y); bool IsPhaserDetected(); + void DrawPhaserCrosshair(int x, int y); + void SetLightPhaserCrosshair(bool enable, LightPhaserCrosshairShape shape, LightPhaserCrosshairColor color); private: void ScanLine(int line); @@ -115,6 +135,9 @@ class Video Overscan m_Overscan; HideLeftBar m_HideLeftBar; int m_iHideLeftBarOffset; + bool m_bLightPhaserCrosshair; + LightPhaserCrosshairShape m_LightPhaserCrosshairShape; + LightPhaserCrosshairColor m_LightPhaserCrosshairColor; struct Phaser {