mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Implemented basic Overwatch parsing
This commit is contained in:
parent
f1b7c667a7
commit
0b889c3b0c
@ -437,6 +437,7 @@
|
|||||||
<Compile Include="Styles\DropTargetAdorners\DropTargetMetroHighlightAdorner.cs" />
|
<Compile Include="Styles\DropTargetAdorners\DropTargetMetroHighlightAdorner.cs" />
|
||||||
<Compile Include="Styles\DropTargetAdorners\DropTargetMetroInsertionAdorner.cs" />
|
<Compile Include="Styles\DropTargetAdorners\DropTargetMetroInsertionAdorner.cs" />
|
||||||
<Compile Include="Utilities\ColorHelpers.cs" />
|
<Compile Include="Utilities\ColorHelpers.cs" />
|
||||||
|
<Compile Include="Utilities\DataReaders\MmfReader.cs" />
|
||||||
<Compile Include="Utilities\ExtensionMethods.cs" />
|
<Compile Include="Utilities\ExtensionMethods.cs" />
|
||||||
<Compile Include="Utilities\GameState\GameDataReceivedEventArgs.cs" />
|
<Compile Include="Utilities\GameState\GameDataReceivedEventArgs.cs" />
|
||||||
<Compile Include="Utilities\GameState\GameStateWebServer.cs" />
|
<Compile Include="Utilities\GameState\GameStateWebServer.cs" />
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
using Artemis.DeviceProviders.Razer.Utilities;
|
using Artemis.DeviceProviders.Razer.Utilities;
|
||||||
using Corale.Colore.Core;
|
using Corale.Colore.Core;
|
||||||
using Corale.Colore.Razer;
|
using Corale.Colore.Razer;
|
||||||
|
using Corale.Colore.Razer.Keyboard;
|
||||||
using Constants = Corale.Colore.Razer.Keyboard.Constants;
|
using Constants = Corale.Colore.Razer.Keyboard.Constants;
|
||||||
|
|
||||||
namespace Artemis.DeviceProviders.Razer
|
namespace Artemis.DeviceProviders.Razer
|
||||||
@ -42,7 +43,6 @@ namespace Artemis.DeviceProviders.Razer
|
|||||||
public override void DrawBitmap(Bitmap bitmap)
|
public override void DrawBitmap(Bitmap bitmap)
|
||||||
{
|
{
|
||||||
var razerArray = RazerUtilities.BitmapColorArray(bitmap, Height, Width);
|
var razerArray = RazerUtilities.BitmapColorArray(bitmap, Height, Width);
|
||||||
|
|
||||||
Chroma.Instance.Keyboard.SetCustom(razerArray);
|
Chroma.Instance.Keyboard.SetCustom(razerArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -155,7 +155,7 @@ namespace Artemis.Managers
|
|||||||
headset.UpdateDevice(renderEffect.GenerateHeadsetBrush());
|
headset.UpdateDevice(renderEffect.GenerateHeadsetBrush());
|
||||||
|
|
||||||
// debugging TODO: Disable when window isn't shown (in Debug VM, or get rid of it, w/e)
|
// debugging TODO: Disable when window isn't shown (in Debug VM, or get rid of it, w/e)
|
||||||
_events.PublishOnUIThread(new ChangeBitmap(bitmap));
|
//_events.PublishOnUIThread(new ChangeBitmap(bitmap));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,5 +4,14 @@ namespace Artemis.Modules.Games.Overwatch
|
|||||||
{
|
{
|
||||||
public class OverwatchDataModel : IGameDataModel
|
public class OverwatchDataModel : IGameDataModel
|
||||||
{
|
{
|
||||||
|
public OverwatchStatus Status { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OverwatchStatus
|
||||||
|
{
|
||||||
|
Unkown,
|
||||||
|
InMainMenu,
|
||||||
|
InCharacterSelection,
|
||||||
|
InGame
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,25 +1,37 @@
|
|||||||
using System.Drawing;
|
using System;
|
||||||
using System.IO;
|
using System.Drawing;
|
||||||
using System.IO.MemoryMappedFiles;
|
using System.Linq.Dynamic;
|
||||||
|
using Artemis.Events;
|
||||||
using Artemis.Managers;
|
using Artemis.Managers;
|
||||||
using Artemis.Models;
|
using Artemis.Models;
|
||||||
using Artemis.Models.Profiles;
|
using Artemis.Models.Profiles;
|
||||||
|
using Artemis.Utilities;
|
||||||
|
using Artemis.Utilities.DataReaders;
|
||||||
|
using Caliburn.Micro;
|
||||||
using Brush = System.Windows.Media.Brush;
|
using Brush = System.Windows.Media.Brush;
|
||||||
|
using Color = System.Windows.Media.Color;
|
||||||
|
|
||||||
namespace Artemis.Modules.Games.Overwatch
|
namespace Artemis.Modules.Games.Overwatch
|
||||||
{
|
{
|
||||||
public class OverwatchModel : GameModel
|
public class OverwatchModel : GameModel
|
||||||
{
|
{
|
||||||
public OverwatchModel(MainManager mainManager, OverwatchSettings settings)
|
private readonly IEventAggregator _events;
|
||||||
|
|
||||||
|
public OverwatchModel(IEventAggregator events, MainManager mainManager, OverwatchSettings settings)
|
||||||
: base(mainManager, settings, new OverwatchDataModel())
|
: base(mainManager, settings, new OverwatchDataModel())
|
||||||
{
|
{
|
||||||
|
_events = events;
|
||||||
Name = "Overwatch";
|
Name = "Overwatch";
|
||||||
ProcessName = "notepad";
|
ProcessName = "Overwatch";
|
||||||
Scale = 4;
|
Scale = 4;
|
||||||
Enabled = Settings.Enabled;
|
Enabled = Settings.Enabled;
|
||||||
Initialized = false;
|
Initialized = false;
|
||||||
|
|
||||||
|
MmfReader = new MmfReader("overwatchMmf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MmfReader MmfReader { get; set; }
|
||||||
|
|
||||||
public int Scale { get; set; }
|
public int Scale { get; set; }
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
@ -35,41 +47,27 @@ namespace Artemis.Modules.Games.Overwatch
|
|||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
var gameDataModel = (OverwatchDataModel) GameDataModel;
|
var gameDataModel = (OverwatchDataModel) GameDataModel;
|
||||||
var mffData = ReadMmf("overwatchMmf");
|
var colors = MmfReader.GetColorArray();
|
||||||
if (mffData == null)
|
if (colors == null)
|
||||||
return;
|
return;
|
||||||
var data = mffData.Split(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
private string ReadMmf(string overwatchmff)
|
var bitmap = new Bitmap(22, 6);
|
||||||
{
|
|
||||||
try
|
using (var g = Graphics.FromImage(bitmap))
|
||||||
{
|
{
|
||||||
// opening not-persistent, pagefile-based memory-mapped file
|
for (var y = 0; y < 6; y++)
|
||||||
using (var mmf = MemoryMappedFile.OpenExisting(overwatchmff))
|
|
||||||
{
|
{
|
||||||
// open the stream to read from the file
|
for (var x = 0; x < 22; x++)
|
||||||
using (var stream = mmf.CreateViewStream())
|
|
||||||
{
|
{
|
||||||
// Read from the shared memory, just for this example we know there is a string
|
g.DrawRectangle(new Pen(ColorHelpers.ToDrawingColor(colors[y, x])), y, x, 1, 1 );
|
||||||
var reader = new BinaryReader(stream);
|
|
||||||
var res = string.Empty;
|
|
||||||
string str;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
str = reader.ReadString();
|
|
||||||
if (!string.IsNullOrEmpty(str) && str[0] != 0)
|
|
||||||
res = res + str;
|
|
||||||
} while (!string.IsNullOrEmpty(str));
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException)
|
_events.PublishOnUIThread(new ChangeBitmap(bitmap));
|
||||||
{
|
if (colors[0, 0].Equals(Color.FromRgb(55, 30, 0)))
|
||||||
return null;
|
gameDataModel.Status = OverwatchStatus.InMainMenu;
|
||||||
//ignored
|
else if (colors[0, 0].Equals(Color.FromRgb(3, 5, 11)))
|
||||||
}
|
gameDataModel.Status = OverwatchStatus.InGame;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Bitmap GenerateBitmap()
|
public override Bitmap GenerateBitmap()
|
||||||
|
|||||||
@ -8,7 +8,7 @@ namespace Artemis.Modules.Games.Overwatch
|
|||||||
public sealed class OverwatchViewModel : GameViewModel
|
public sealed class OverwatchViewModel : GameViewModel
|
||||||
{
|
{
|
||||||
public OverwatchViewModel(MainManager main, IEventAggregator events, IProfileEditorViewModelFactory pFactory)
|
public OverwatchViewModel(MainManager main, IEventAggregator events, IProfileEditorViewModelFactory pFactory)
|
||||||
: base(main, new OverwatchModel(main, new OverwatchSettings()), events, pFactory)
|
: base(main, new OverwatchModel(events, main, new OverwatchSettings()), events, pFactory)
|
||||||
{
|
{
|
||||||
DisplayName = "Overwatch";
|
DisplayName = "Overwatch";
|
||||||
MainManager.EffectManager.EffectModels.Add(GameModel);
|
MainManager.EffectManager.EffectModels.Add(GameModel);
|
||||||
|
|||||||
96
Artemis/Artemis/Utilities/DataReaders/MmfReader.cs
Normal file
96
Artemis/Artemis/Utilities/DataReaders/MmfReader.cs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.MemoryMappedFiles;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
namespace Artemis.Utilities.DataReaders
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A helper class for reading memory managed files
|
||||||
|
/// </summary>
|
||||||
|
public class MmfReader
|
||||||
|
{
|
||||||
|
private DateTime _lastFailure;
|
||||||
|
|
||||||
|
public MmfReader(string mmfName)
|
||||||
|
{
|
||||||
|
MmfName = mmfName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MmfName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Turns the MMF into an color array
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Color[,] GetColorArray()
|
||||||
|
{
|
||||||
|
var mffString = ReadMmf(MmfName);
|
||||||
|
if (string.IsNullOrEmpty(mffString))
|
||||||
|
return null;
|
||||||
|
var intermediateArray = mffString.Split('|');
|
||||||
|
if (intermediateArray[0] == "1")
|
||||||
|
return null;
|
||||||
|
var array = intermediateArray[1].Substring(1).Split(' ');
|
||||||
|
if (!array.Any())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var colors = new Color[6, 22];
|
||||||
|
foreach (var intermediate in array)
|
||||||
|
{
|
||||||
|
if (intermediate.Length > 16)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Can't parse to a byte directly since it may contain values >254
|
||||||
|
var parts = intermediate.Split(',').Select(int.Parse).ToArray();
|
||||||
|
if (parts[0] >= 5 && parts[1] >= 21)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
colors[parts[0], parts[1]] = Color.FromRgb((byte) parts[2], (byte) parts[3], (byte) parts[4]);
|
||||||
|
}
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the contents of the given MFF into a string
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string ReadMmf(string fileName)
|
||||||
|
{
|
||||||
|
// Don't read the file within one second after failing
|
||||||
|
//if (DateTime.Now - _lastFailure > new TimeSpan(0, 0, 1))
|
||||||
|
// return null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var mmf = MemoryMappedFile.OpenExisting(fileName))
|
||||||
|
{
|
||||||
|
using (var stream = mmf.CreateViewStream())
|
||||||
|
{
|
||||||
|
using (var binReader = new BinaryReader(stream))
|
||||||
|
{
|
||||||
|
var allBytes = binReader.ReadBytes((int) stream.Length);
|
||||||
|
return Encoding.UTF8.GetString(allBytes, 0, allBytes.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException)
|
||||||
|
{
|
||||||
|
_lastFailure = DateTime.Now;
|
||||||
|
return null;
|
||||||
|
//ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,104 +0,0 @@
|
|||||||
// Original work by VRocker https://github.com/VRocker/LogiLed2Corsair
|
|
||||||
// I'm mainly a C# developer, and these modification aren't a piece of art, but it suits our needs.
|
|
||||||
|
|
||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 VRocker
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#include "Logger.h"
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
|
|
||||||
// Ok this looks butt-ugleh but its just to force the default log level to debug if we compile in debug
|
|
||||||
#ifdef _DEBUG
|
|
||||||
LogLevel CLogger::m_eLogLevel = LogLevel::Debug;
|
|
||||||
#else
|
|
||||||
LogLevel CLogger::m_eLogLevel = LogLevel::All;
|
|
||||||
#endif
|
|
||||||
FILE* CLogger::m_pFile = 0;
|
|
||||||
|
|
||||||
void CLogger::InitLogging(const char* szFile)
|
|
||||||
{
|
|
||||||
if (!m_pFile)
|
|
||||||
{
|
|
||||||
m_pFile = fopen(szFile, "a+");
|
|
||||||
if (!m_pFile)
|
|
||||||
{
|
|
||||||
// Hum, we couldn't open the file for writing
|
|
||||||
printf("ERROR: Unable to open log file %s.\n", szFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CLogger::EndLogging(void)
|
|
||||||
{
|
|
||||||
if (m_pFile)
|
|
||||||
{
|
|
||||||
fclose(m_pFile);
|
|
||||||
m_pFile = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CLogger::OutputLog_s(const char* sz, const LogLevel eLevel)
|
|
||||||
{
|
|
||||||
// If the level of this log entry is less important than what we are told to log, just return
|
|
||||||
if (eLevel < m_eLogLevel)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If we don't have a file to write to, bail.
|
|
||||||
if (!m_pFile)
|
|
||||||
return;
|
|
||||||
|
|
||||||
char szOutput[512] = { 0 };
|
|
||||||
|
|
||||||
time_t rawtime;
|
|
||||||
struct tm* timeinfo;
|
|
||||||
|
|
||||||
time(&rawtime);
|
|
||||||
timeinfo = localtime(&rawtime);
|
|
||||||
|
|
||||||
// Timestamp the log entry
|
|
||||||
size_t uiLen = sprintf(szOutput, "<%.2d/%.2d/%.2d - %.2d:%.2d:%.2d> %s\n", timeinfo->tm_mday, timeinfo->tm_mon + 1, timeinfo->tm_year + 1900, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, sz);
|
|
||||||
|
|
||||||
// Write the text to the file
|
|
||||||
fwrite(szOutput, 1, uiLen, m_pFile);
|
|
||||||
// Flush the log file to the disk. May move this to a seperate function
|
|
||||||
fflush(m_pFile);
|
|
||||||
|
|
||||||
// Output the text to any console that may be attached
|
|
||||||
printf("%s", szOutput);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CLogger::OutputLog(const char* sz, const LogLevel eLevel, ...)
|
|
||||||
{
|
|
||||||
char szText[1024] = { 0 };
|
|
||||||
va_list marker;
|
|
||||||
va_start(marker, eLevel);
|
|
||||||
vsprintf(szText, sz, marker);
|
|
||||||
va_end(marker);
|
|
||||||
|
|
||||||
// Since this function is pretty much the same as the safer function, we'll just redirect it there
|
|
||||||
OutputLog_s(szText, eLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
// Original work by VRocker https://github.com/VRocker/LogiLed2Corsair
|
|
||||||
// I'm mainly a C# developer, and these modification aren't a piece of art, but it suits our needs.
|
|
||||||
|
|
||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 VRocker
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef _LOGGER_H
|
|
||||||
#define _LOGGER_H
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
enum class LogLevel
|
|
||||||
{
|
|
||||||
Debug,
|
|
||||||
All,
|
|
||||||
Critical,
|
|
||||||
Warning,
|
|
||||||
Information,
|
|
||||||
User,
|
|
||||||
Internal,
|
|
||||||
None,
|
|
||||||
|
|
||||||
// Just to force the compiler to treat the enum options as an int
|
|
||||||
FORCE_32BIT = 0x7fffffff
|
|
||||||
};
|
|
||||||
|
|
||||||
class CLogger
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static LogLevel GetLogLevel(void)
|
|
||||||
{
|
|
||||||
return m_eLogLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SetLogLevel(const LogLevel e)
|
|
||||||
{
|
|
||||||
#ifndef _DEBUG
|
|
||||||
if (e == LogLevel::Debug) return;
|
|
||||||
#endif
|
|
||||||
m_eLogLevel = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void InitLogging(const char* szFile);
|
|
||||||
// Always remember to end logging when you are finished otherwise you will have file handles floating around
|
|
||||||
static void EndLogging(void);
|
|
||||||
|
|
||||||
// Output the text to a log file.
|
|
||||||
static void OutputLog_s(const char* sz, const LogLevel eLevel);
|
|
||||||
static void OutputLog(const char* sz, const LogLevel eLevel, ...);
|
|
||||||
|
|
||||||
static FILE* GetFile()
|
|
||||||
{
|
|
||||||
return m_pFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static LogLevel m_eLogLevel;
|
|
||||||
static FILE* m_pFile;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@ -126,11 +126,9 @@
|
|||||||
<None Include="Razer2Artemis.def" />
|
<None Include="Razer2Artemis.def" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="Logger.cpp" />
|
|
||||||
<ClCompile Include="main.cpp" />
|
<ClCompile Include="main.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Logger.h" />
|
|
||||||
<ClInclude Include="main.h" />
|
<ClInclude Include="main.h" />
|
||||||
<ClInclude Include="RzChromaSDKDefines.h" />
|
<ClInclude Include="RzChromaSDKDefines.h" />
|
||||||
<ClInclude Include="RzChromaSDKTypes.h" />
|
<ClInclude Include="RzChromaSDKTypes.h" />
|
||||||
|
|||||||
@ -23,17 +23,11 @@
|
|||||||
<ClCompile Include="main.cpp">
|
<ClCompile Include="main.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Logger.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="main.h">
|
<ClInclude Include="main.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Logger.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="RzChromaSDKDefines.h">
|
<ClInclude Include="RzChromaSDKDefines.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|||||||
@ -1,212 +1,165 @@
|
|||||||
// Original work by VRocker https://github.com/VRocker/LogiLed2Corsair
|
|
||||||
// I'm mainly a C# developer, and these modification aren't a piece of art, but it suits our needs.
|
|
||||||
|
|
||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 VRocker
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <thread>
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include "Logger.h"
|
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
TCHAR szName[] = TEXT("overwatchMmf");
|
TCHAR szName[] = TEXT("overwatchMmf");
|
||||||
TCHAR szMsg[] = TEXT("Message from first process.");
|
TCHAR szMsg[] = TEXT("Message from first process.");
|
||||||
#define BUF_SIZE 2000
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define BUF_SIZE 4096
|
||||||
|
|
||||||
static bool g_hasInitialised = false;
|
static bool g_hasInitialised = false;
|
||||||
const char* game = "";
|
const char* game = "";
|
||||||
|
|
||||||
void cleanup()
|
|
||||||
{
|
|
||||||
CLogger::EndLogging();
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE hMapFile;
|
HANDLE hMapFile;
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID)
|
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID)
|
||||||
{
|
{
|
||||||
switch (fdwReason)
|
if (fdwReason == DLL_PROCESS_ATTACH)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
// Get the process that loaded the DLL
|
||||||
{
|
TCHAR overwatchFind[] = _T("Overwatch");
|
||||||
atexit(cleanup);
|
TCHAR szPath[MAX_PATH];
|
||||||
|
GetModuleFileName(nullptr, szPath, MAX_PATH);
|
||||||
|
|
||||||
CLogger::InitLogging("Log.txt");
|
if (_tcscmp(szPath, overwatchFind) != 0)
|
||||||
CLogger::SetLogLevel(LogLevel::Debug);
|
game = "overwatch";
|
||||||
|
|
||||||
// Get the process that loaded the DLL
|
// Setup mmf
|
||||||
TCHAR overwatchFind[] = _T("Overwatch");
|
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, BUF_SIZE, szName);
|
||||||
TCHAR szPath[MAX_PATH];
|
|
||||||
GetModuleFileName(nullptr, szPath, MAX_PATH);
|
|
||||||
|
|
||||||
if (_tcscmp(szPath, overwatchFind) != 0)
|
|
||||||
game = "overwatch";
|
|
||||||
|
|
||||||
CLogger::OutputLog("Attached to process.", LogLevel::Debug);
|
|
||||||
|
|
||||||
// Setup mmf
|
|
||||||
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, BUF_SIZE, szName);
|
|
||||||
|
|
||||||
if (hMapFile == nullptr)
|
|
||||||
{
|
|
||||||
CLogger::OutputLog("Could not create file mapping object (error %i)", LogLevel::Debug, GetLastError());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DLL_PROCESS_DETACH:
|
|
||||||
{
|
|
||||||
CLogger::OutputLog_s("Detached from process.", LogLevel::Debug);
|
|
||||||
CloseHandle(hMapFile);
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteMmf(const char* msg)
|
template <typename ... Args>
|
||||||
|
std::string string_format(const std::string& format, Args ... args)
|
||||||
|
{
|
||||||
|
size_t size = snprintf(nullptr, 0, format.c_str(), args ...) + 1; // Extra space for '\0'
|
||||||
|
std::unique_ptr<char[]> buf(new char[size]);
|
||||||
|
snprintf(buf.get(), size, format.c_str(), args ...);
|
||||||
|
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WriteMmf(std::string msg)
|
||||||
{
|
{
|
||||||
if (hMapFile == nullptr)
|
if (hMapFile == nullptr)
|
||||||
{
|
{
|
||||||
CLogger::OutputLog_s("Could not write to mmf", LogLevel::Debug);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LPCTSTR pBuf;
|
LPCTSTR pBuf;
|
||||||
pBuf = static_cast<LPTSTR>(MapViewOfFile(hMapFile, // handle to map object
|
pBuf = static_cast<LPTSTR>(MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE));
|
||||||
FILE_MAP_ALL_ACCESS, // read/write permission
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
BUF_SIZE));
|
|
||||||
|
|
||||||
if (pBuf == nullptr)
|
if (pBuf == nullptr)
|
||||||
{
|
{
|
||||||
CLogger::OutputLog("Could not map view of file (error %i)", LogLevel::Debug, GetLastError());
|
|
||||||
CloseHandle(hMapFile);
|
CloseHandle(hMapFile);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyMemory((PVOID)pBuf, msg, (_tcslen(msg) * sizeof(TCHAR)));
|
CopyMemory((PVOID)pBuf, msg.c_str(), msg.size());
|
||||||
UnmapViewOfFile(pBuf);
|
UnmapViewOfFile(pBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
RZRESULT Init()
|
RZRESULT Init()
|
||||||
{
|
{
|
||||||
CLogger::OutputLog_s("Razer Init called.", LogLevel::Debug);
|
|
||||||
g_hasInitialised = true;
|
g_hasInitialised = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZRESULT UnInit()
|
RZRESULT UnInit()
|
||||||
{
|
{
|
||||||
CLogger::OutputLog_s("Razer UnInit called.", LogLevel::Debug);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZRESULT CreateEffect(RZDEVICEID DeviceId, ChromaSDK::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId)
|
RZRESULT CreateEffect(RZDEVICEID DeviceId, ChromaSDK::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId)
|
||||||
{
|
{
|
||||||
CLogger::OutputLog_s("Razer CreateEffect called.", LogLevel::Debug);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZRESULT CreateKeyboardEffect(ChromaSDK::Keyboard::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId)
|
RZRESULT CreateKeyboardEffect(ChromaSDK::Keyboard::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId)
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::string res = "";
|
||||||
auto keys = *static_cast<struct CUSTOM_KEY_EFFECT_TYPE*>(pParam);
|
if (Effect == Keyboard::CHROMA_CUSTOM) {
|
||||||
|
res += "0|";
|
||||||
|
auto keys = *static_cast<struct Keyboard::CUSTOM_EFFECT_TYPE*>(pParam);
|
||||||
|
|
||||||
for (auto y = 0; y < 6; y++)
|
for (auto y = 0; y < 6; y++)
|
||||||
{
|
|
||||||
for (auto x = 0; x < 22; x++)
|
|
||||||
{
|
{
|
||||||
auto r = (int) GetRValue(keys.Color[y][x]);
|
for (auto x = 0; x < 22; x++)
|
||||||
auto g = (int) GetGValue(keys.Color[y][x]);
|
{
|
||||||
auto b = (int) GetGValue(keys.Color[y][x]);
|
auto r = GetRValue(keys.Color[y][x]);
|
||||||
os << " [" << x << "][" << y << "](" << r << "," << g << "," << b << ")";
|
auto g = GetGValue(keys.Color[y][x]);
|
||||||
|
auto b = GetBValue(keys.Color[y][x]);
|
||||||
|
res += string_format(" %d,%d,%d,%d,%d", y, x, r, g, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Effect == Keyboard::CHROMA_CUSTOM_KEY) {
|
||||||
|
res += "1|";
|
||||||
|
auto keys = *static_cast<struct Keyboard::CUSTOM_KEY_EFFECT_TYPE*>(pParam);
|
||||||
|
|
||||||
|
for (auto y = 0; y < 6; y++)
|
||||||
|
{
|
||||||
|
for (auto x = 0; x < 22; x++)
|
||||||
|
{
|
||||||
|
auto r = GetRValue(keys.Color[y][x]);
|
||||||
|
auto g = GetGValue(keys.Color[y][x]);
|
||||||
|
auto b = GetBValue(keys.Color[y][x]);
|
||||||
|
res += string_format(" %d,%d,%d,%d,%d", y, x, r, g, b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CLogger::OutputLog_s("Razer CreateKeyboardEffect called", LogLevel::Debug);
|
WriteMmf(res);
|
||||||
WriteMmf(os.str().c_str());
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZRESULT CreateMouseEffect(ChromaSDK::Mouse::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId)
|
RZRESULT CreateMouseEffect(ChromaSDK::Mouse::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId)
|
||||||
{
|
{
|
||||||
CLogger::OutputLog_s("Razer CreateMouseEffect called.", LogLevel::Debug);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZRESULT CreateHeadsetEffect(ChromaSDK::Headset::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId)
|
RZRESULT CreateHeadsetEffect(ChromaSDK::Headset::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId)
|
||||||
{
|
{
|
||||||
CLogger::OutputLog_s("Razer CreateHeadsetEffect called.", LogLevel::Debug);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZRESULT CreateMousepadEffect(ChromaSDK::Mousepad::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId)
|
RZRESULT CreateMousepadEffect(ChromaSDK::Mousepad::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId)
|
||||||
{
|
{
|
||||||
CLogger::OutputLog_s("Razer CreateMousepadEffect called.", LogLevel::Debug);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZRESULT CreateKeypadEffect(ChromaSDK::Keypad::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId)
|
RZRESULT CreateKeypadEffect(ChromaSDK::Keypad::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId)
|
||||||
{
|
{
|
||||||
CLogger::OutputLog_s("Razer CreateKeypadEffect called.", LogLevel::Debug);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZRESULT DeleteEffect(RZEFFECTID EffectId)
|
RZRESULT DeleteEffect(RZEFFECTID EffectId)
|
||||||
{
|
{
|
||||||
CLogger::OutputLog_s("Razer DeleteEffect called.", LogLevel::Debug);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZRESULT SetEffect(RZEFFECTID EffectId)
|
RZRESULT SetEffect(RZEFFECTID EffectId)
|
||||||
{
|
{
|
||||||
CLogger::OutputLog_s("Razer SetEffect called.", LogLevel::Debug);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZRESULT RegisterEventNotification(HWND hWnd)
|
RZRESULT RegisterEventNotification(HWND hWnd)
|
||||||
{
|
{
|
||||||
CLogger::OutputLog_s("Razer RegisterEventNotification called.", LogLevel::Debug);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZRESULT UnregisterEventNotification()
|
RZRESULT UnregisterEventNotification()
|
||||||
{
|
{
|
||||||
CLogger::OutputLog_s("Razer UnregisterEventNotification called.", LogLevel::Debug);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZRESULT QueryDevice(RZDEVICEID DeviceId, DEVICE_INFO_TYPE& DeviceInfo)
|
RZRESULT QueryDevice(RZDEVICEID DeviceId, DEVICE_INFO_TYPE& DeviceInfo)
|
||||||
{
|
{
|
||||||
CLogger::OutputLog_s("Razer QueryDevice called.", LogLevel::Debug);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
15
Artemis/Razer2Artemis/utils.cpp
Normal file
15
Artemis/Razer2Artemis/utils.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
template <typename ... Args>
|
||||||
|
string string_format(const std::string& format, Args ... args)
|
||||||
|
{
|
||||||
|
size_t size = snprintf(nullptr, 0, format.c_str(), args ...) + 1; // Extra space for '\0'
|
||||||
|
unique_ptr<char[]> buf(new char[size]);
|
||||||
|
snprintf(buf.get(), size, format.c_str(), args ...);
|
||||||
|
return string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
||||||
|
}
|
||||||
12
Artemis/Razer2Artemis/utils.h
Normal file
12
Artemis/Razer2Artemis/utils.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
template <typename ... Args>
|
||||||
|
std::string string_format(const std::string& format, Args ... args)
|
||||||
|
{
|
||||||
|
size_t size = snprintf(nullptr, 0, format.c_str(), args ...) + 1; // Extra space for '\0'
|
||||||
|
std::unique_ptr<char[]> buf(new char[size]);
|
||||||
|
snprintf(buf.get(), size, format.c_str(), args ...);
|
||||||
|
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user