Skip to content

Commit

Permalink
WiimoteEmu: Implement uDraw GameTablet.
Browse files Browse the repository at this point in the history
  • Loading branch information
jordan-woyak committed Mar 23, 2019
1 parent 672b582 commit 88f43af
Show file tree
Hide file tree
Showing 27 changed files with 870 additions and 273 deletions.
1 change: 1 addition & 0 deletions Source/Core/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ add_library(core
HW/WiimoteEmu/Extension/Drums.cpp
HW/WiimoteEmu/Extension/Guitar.cpp
HW/WiimoteEmu/Extension/Turntable.cpp
HW/WiimoteEmu/Extension/UDrawTablet.cpp
HW/WiimoteReal/WiimoteReal.cpp
HW/WiiSave.cpp
IOS/Device.cpp
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/Core/Core.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@
<ClCompile Include="HW\WiimoteEmu\Extension\Guitar.cpp" />
<ClCompile Include="HW\WiimoteEmu\Extension\Nunchuk.cpp" />
<ClCompile Include="HW\WiimoteEmu\Extension\Turntable.cpp" />
<ClInclude Include="HW\WiimoteEmu\Extension\UDrawTablet.cpp" />
<ClCompile Include="HW\WiimoteEmu\I2CBus.cpp" />
<ClCompile Include="HW\WiimoteEmu\MotionPlus.cpp" />
<ClCompile Include="HW\WiimoteEmu\Speaker.cpp" />
Expand Down Expand Up @@ -451,6 +452,7 @@
<ClInclude Include="HW\WiimoteEmu\Extension\Guitar.h" />
<ClInclude Include="HW\WiimoteEmu\Extension\Nunchuk.h" />
<ClInclude Include="HW\WiimoteEmu\Extension\Turntable.h" />
<ClInclude Include="HW\WiimoteEmu\Extension\UDrawTablet.h" />
<ClInclude Include="HW\WiimoteEmu\I2CBus.h" />
<ClInclude Include="HW\WiimoteEmu\MotionPlus.h" />
<ClInclude Include="HW\WiimoteEmu\Speaker.h" />
Expand Down
8 changes: 7 additions & 1 deletion Source/Core/Core/Core.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,9 @@
<ClCompile Include="HW\WiimoteEmu\Extension\Turntable.cpp">
<Filter>HW %28Flipper/Hollywood%29\Wiimote\Emu\Extension</Filter>
</ClCompile>
<ClCompile Include="HW\WiimoteEmu\Extension\UDrawTablet.cpp">
<Filter>HW %28Flipper/Hollywood%29\Wiimote\Emu\Extension</Filter>
</ClCompile>
<ClCompile Include="HW\WiimoteEmu\Extension\Extension.cpp">
<Filter>HW %28Flipper/Hollywood%29\Wiimote\Emu\Extension</Filter>
</ClCompile>
Expand Down Expand Up @@ -1625,6 +1628,9 @@
<ClInclude Include="HW\WiimoteEmu\Extension\Turntable.h">
<Filter>HW %28Flipper/Hollywood%29\Wiimote\Emu\Extension</Filter>
</ClInclude>
<ClInclude Include="HW\WiimoteEmu\Extension\UDrawTablet.h">
<Filter>HW %28Flipper/Hollywood%29\Wiimote\Emu\Extension</Filter>
</ClInclude>
<ClInclude Include="HW\WiimoteEmu\Extension\Extension.h">
<Filter>HW %28Flipper/Hollywood%29\Wiimote\Emu\Extension</Filter>
</ClInclude>
Expand All @@ -1638,4 +1644,4 @@
<ItemGroup>
<Text Include="CMakeLists.txt" />
</ItemGroup>
</Project>
</Project>
6 changes: 6 additions & 0 deletions Source/Core/Core/HW/Wiimote.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ ControllerEmu::ControlGroup* GetTurntableGroup(int number, WiimoteEmu::Turntable
->GetTurntableGroup(group);
}

ControllerEmu::ControlGroup* GetUDrawTabletGroup(int number, WiimoteEmu::UDrawTabletGroup group)
{
return static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))
->GetUDrawTabletGroup(group);
}

void Shutdown()
{
s_config.UnregisterHotplugCallback();
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/Core/HW/Wiimote.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ enum class ClassicGroup;
enum class GuitarGroup;
enum class DrumsGroup;
enum class TurntableGroup;
enum class UDrawTabletGroup;
} // namespace WiimoteEmu

enum
Expand Down Expand Up @@ -75,6 +76,7 @@ ControllerEmu::ControlGroup* GetClassicGroup(int number, WiimoteEmu::ClassicGrou
ControllerEmu::ControlGroup* GetGuitarGroup(int number, WiimoteEmu::GuitarGroup group);
ControllerEmu::ControlGroup* GetDrumsGroup(int number, WiimoteEmu::DrumsGroup group);
ControllerEmu::ControlGroup* GetTurntableGroup(int number, WiimoteEmu::TurntableGroup group);
ControllerEmu::ControlGroup* GetUDrawTabletGroup(int number, WiimoteEmu::UDrawTabletGroup group);

void ControlChannel(int number, u16 channel_id, const void* data, u32 size);
void InterruptChannel(int number, u16 channel_id, const void* data, u32 size);
Expand Down
693 changes: 462 additions & 231 deletions Source/Core/Core/HW/WiimoteEmu/Encryption.cpp

Large diffs are not rendered by default.

48 changes: 43 additions & 5 deletions Source/Core/Core/HW/WiimoteEmu/Encryption.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,59 @@

#pragma once

#include <array>

#include "Common/CommonTypes.h"

namespace WiimoteEmu
{
class EncryptionKey
{
public:
void Generate(const u8* keydata);
void Encrypt(u8* data, u32 addr, u32 len) const;
void Decrypt(u8* data, u32 addr, u32 len) const;

using RandData = std::array<u8, 10>;
using KeyData = std::array<u8, 6>;

void GenerateTables(const RandData& rand, const KeyData& key, const u32 idx, const u8 offset);

std::array<u8, 8> ft = {};
std::array<u8, 8> sb = {};
};

class KeyGen
{
public:
virtual ~KeyGen() = default;

void Encrypt(u8* data, int addr, u8 len) const;
void Decrypt(u8* data, int addr, u8 len) const;
using ExtKeyData = std::array<u8, 16>;

EncryptionKey GenerateFromExtensionKeyData(const ExtKeyData& key_data) const;

protected:
virtual EncryptionKey::KeyData GenerateKeyData(const EncryptionKey::RandData& rand,
u32 idx) const = 0;
virtual EncryptionKey GenerateTables(const EncryptionKey::RandData& rand,
const EncryptionKey::KeyData& key, u32 idx) const = 0;
};

class KeyGen1stParty final : public KeyGen
{
private:
EncryptionKey::KeyData GenerateKeyData(const EncryptionKey::RandData& rand,
u32 idx) const final override;
EncryptionKey GenerateTables(const EncryptionKey::RandData& rand,
const EncryptionKey::KeyData& key, u32 idx) const final override;
};

class KeyGen3rdParty final : public KeyGen
{
private:
u8 ft[8] = {};
u8 sb[8] = {};
EncryptionKey::KeyData GenerateKeyData(const EncryptionKey::RandData& rand,
u32 idx) const final override;
EncryptionKey GenerateTables(const EncryptionKey::RandData& rand,
const EncryptionKey::KeyData& key, u32 idx) const final override;
};

} // namespace WiimoteEmu
5 changes: 3 additions & 2 deletions Source/Core/Core/HW/WiimoteEmu/Extension/Classic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ constexpr std::array<u16, 4> classic_dpad_bitmasks{{
Classic::PAD_RIGHT,
}};

Classic::Classic() : EncryptedExtension(_trans("Classic"))
Classic::Classic() : Extension1stParty(_trans("Classic"))
{
// buttons
groups.emplace_back(m_buttons = new ControllerEmu::Buttons(_trans("Buttons")));
Expand Down Expand Up @@ -172,7 +172,8 @@ bool Classic::IsButtonPressed() const

void Classic::Reset()
{
m_reg = {};
EncryptedExtension::Reset();

m_reg.identifier = classic_id;

// Build calibration data:
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/HW/WiimoteEmu/Extension/Classic.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ enum class ClassicGroup
RightStick
};

class Classic : public EncryptedExtension
class Classic : public Extension1stParty
{
public:
union ButtonFormat
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/Core/HW/WiimoteEmu/Extension/Drums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ constexpr std::array<u16, 2> drum_button_bitmasks{{
Drums::BUTTON_PLUS,
}};

Drums::Drums() : EncryptedExtension(_trans("Drums"))
Drums::Drums() : Extension1stParty(_trans("Drums"))
{
// pads
groups.emplace_back(m_pads = new ControllerEmu::Buttons(_trans("Pads")));
Expand Down Expand Up @@ -106,7 +106,8 @@ bool Drums::IsButtonPressed() const

void Drums::Reset()
{
m_reg = {};
EncryptedExtension::Reset();

m_reg.identifier = drums_id;

// TODO: Is there calibration data?
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/Core/HW/WiimoteEmu/Extension/Drums.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ enum class DrumsGroup
Stick
};

// TODO: Do the drums ever use encryption?
class Drums : public EncryptedExtension
// The Drums use the "1st-party" extension encryption scheme.
class Drums : public Extension1stParty
{
public:
struct DataFormat
Expand Down
55 changes: 41 additions & 14 deletions Source/Core/Core/HW/WiimoteEmu/Extension/Extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "Common/Compiler.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"

#include "Common/Logging/Log.h"

namespace WiimoteEmu
{
Extension::Extension(const char* name) : m_name(name)
Expand Down Expand Up @@ -85,15 +87,16 @@ int EncryptedExtension::BusRead(u8 slave_addr, u8 addr, int count, u8* data_out)

auto const result = RawRead(&m_reg, addr, count, data_out);

// Encrypt data read from extension register
// Encrypt data read from extension register.
if (ENCRYPTION_ENABLED == m_reg.encryption)
{
// INFO_LOG(WIIMOTE, "Encrypted read.");
ext_key.Encrypt(data_out, addr, (u8)count);
}
else
{
// INFO_LOG(WIIMOTE, "Unencrypted read.");
if (m_is_key_dirty)
{
UpdateEncryptionKey();
m_is_key_dirty = false;
}

ext_key.Encrypt(data_out, addr, count);
}

return result;
Expand All @@ -106,24 +109,48 @@ int EncryptedExtension::BusWrite(u8 slave_addr, u8 addr, int count, const u8* da

auto const result = RawWrite(&m_reg, addr, count, data_in);

// TODO: make this check less ugly:
if (addr + count > 0x40 && addr < 0x50)
constexpr u8 ENCRYPTION_KEY_DATA_BEGIN = offsetof(Register, encryption_key_data);
constexpr u8 ENCRYPTION_KEY_DATA_END = ENCRYPTION_KEY_DATA_BEGIN + 0x10;

if (addr + count > ENCRYPTION_KEY_DATA_BEGIN && addr < ENCRYPTION_KEY_DATA_END)
{
// Run the key generation on all writes in the key area, it doesn't matter
// that we send it parts of a key, only the last full key will have an effect
ext_key.Generate(m_reg.encryption_key_data);
// FYI: Real extensions seem to require the key data written in specifically sized chunks.
// We just run the key generation on all writes to the key area.
m_is_key_dirty = true;
}

return result;
}

void EncryptedExtension::Reset()
{
// Clear register state.
m_reg = {};

// Clear encryption key state.
ext_key = {};
m_is_key_dirty = true;
}

void EncryptedExtension::DoState(PointerWrap& p)
{
p.Do(m_reg);

// No need to sync this when we can regenerate it:
if (p.GetMode() == PointerWrap::MODE_READ)
ext_key.Generate(m_reg.encryption_key_data);
{
// No need to sync the key when we can just regenerate it.
m_is_key_dirty = true;
}
}

void Extension1stParty::UpdateEncryptionKey()
{
ext_key = KeyGen1stParty().GenerateFromExtensionKeyData(m_reg.encryption_key_data);
}

void Extension3rdParty::UpdateEncryptionKey()
{
ext_key = KeyGen3rdParty().GenerateFromExtensionKeyData(m_reg.encryption_key_data);
}

} // namespace WiimoteEmu
27 changes: 25 additions & 2 deletions Source/Core/Core/HW/WiimoteEmu/Extension/Extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class EncryptedExtension : public Extension

// TODO: This is public for TAS reasons.
// TODO: TAS handles encryption poorly.
WiimoteEmu::EncryptionKey ext_key = {};
EncryptionKey ext_key;

protected:
static constexpr int CALIBRATION_CHECKSUM_BYTES = 2;
Expand All @@ -82,7 +82,7 @@ class EncryptedExtension : public Extension
u8 unknown3[0x10];

// address 0x40
u8 encryption_key_data[0x10];
std::array<u8, 0x10> encryption_key_data;
u8 unknown4[0xA0];

// address 0xF0
Expand All @@ -98,9 +98,14 @@ class EncryptedExtension : public Extension

Register m_reg = {};

void Reset() override;
void DoState(PointerWrap& p) override;

virtual void UpdateEncryptionKey() = 0;

private:
bool m_is_key_dirty = true;

static constexpr u8 ENCRYPTION_ENABLED = 0xaa;

bool ReadDeviceDetectPin() const override;
Expand All @@ -109,4 +114,22 @@ class EncryptedExtension : public Extension
int BusWrite(u8 slave_addr, u8 addr, int count, const u8* data_in) override;
};

class Extension1stParty : public EncryptedExtension
{
protected:
using EncryptedExtension::EncryptedExtension;

private:
void UpdateEncryptionKey() final override;
};

class Extension3rdParty : public EncryptedExtension
{
protected:
using EncryptedExtension::EncryptedExtension;

private:
void UpdateEncryptionKey() final override;
};

} // namespace WiimoteEmu
5 changes: 3 additions & 2 deletions Source/Core/Core/HW/WiimoteEmu/Extension/Guitar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ constexpr std::array<u16, 2> guitar_strum_bitmasks{{
Guitar::BAR_DOWN,
}};

Guitar::Guitar() : EncryptedExtension(_trans("Guitar"))
Guitar::Guitar() : Extension1stParty(_trans("Guitar"))
{
// frets
groups.emplace_back(m_frets = new ControllerEmu::Buttons(_trans("Frets")));
Expand Down Expand Up @@ -152,7 +152,8 @@ bool Guitar::IsButtonPressed() const

void Guitar::Reset()
{
m_reg = {};
EncryptedExtension::Reset();

m_reg.identifier = guitar_id;

// TODO: Is there calibration data?
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/Core/HW/WiimoteEmu/Extension/Guitar.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ enum class GuitarGroup
SliderBar
};

// TODO: Does the guitar ever use encryption?
class Guitar : public EncryptedExtension
// The Guitar uses the "1st-party" extension encryption scheme.
class Guitar : public Extension1stParty
{
public:
struct DataFormat
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/Core/HW/WiimoteEmu/Extension/Nunchuk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ constexpr std::array<u8, 2> nunchuk_button_bitmasks{{
Nunchuk::BUTTON_Z,
}};

Nunchuk::Nunchuk() : EncryptedExtension(_trans("Nunchuk"))
Nunchuk::Nunchuk() : Extension1stParty(_trans("Nunchuk"))
{
// buttons
groups.emplace_back(m_buttons = new ControllerEmu::Buttons(_trans("Buttons")));
Expand Down Expand Up @@ -141,7 +141,8 @@ bool Nunchuk::IsButtonPressed() const

void Nunchuk::Reset()
{
m_reg = {};
EncryptedExtension::Reset();

m_reg.identifier = nunchuk_id;

m_swing_state = {};
Expand Down
Loading

0 comments on commit 88f43af

Please sign in to comment.