Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion WheelWizard.Test/Features/MiiDbServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
using Testably.Abstractions;
using WheelWizard.Shared;
using WheelWizard.WiiManagement;
using WheelWizard.WiiManagement.Domain.Mii;
using WheelWizard.WiiManagement.MiiManagement;
using WheelWizard.WiiManagement.MiiManagement.Domain.Mii;

namespace WheelWizard.Test.Features
{
Expand Down
1 change: 1 addition & 0 deletions WheelWizard.Test/Features/MiiSerializerTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using WheelWizard.WiiManagement;
using WheelWizard.WiiManagement.MiiManagement;

namespace WheelWizard.Test.Features;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Microsoft.Extensions.Caching.Memory;
using WheelWizard.MiiImages.Domain;
using WheelWizard.Shared.Services;
using WheelWizard.WiiManagement.Domain.Mii;
using WheelWizard.WiiManagement.MiiManagement.Domain.Mii;

namespace WheelWizard.MiiImages;

Expand Down
25 changes: 13 additions & 12 deletions WheelWizard/Features/MiiImages/MiiStudioDataSerializer.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using System.Text;
using WheelWizard.Services.WiiManagement.SaveData;
using WheelWizard.Helpers;
using WheelWizard.WiiManagement;
using WheelWizard.WiiManagement.Domain.Mii;
using WheelWizard.WiiManagement.MiiManagement;
using WheelWizard.WiiManagement.MiiManagement.Domain.Mii;

namespace WheelWizard.MiiImages;

Expand Down Expand Up @@ -77,7 +78,7 @@ private static byte[] GenerateStudioDataArray(byte[] buf)
// Offsets and logic match the 'else' block (Wii part) of miiFileRead

// --- Basic Info ---
var tmpU16_0 = BigEndianBinaryReader.BufferToUint16(buf, 0);
var tmpU16_0 = BigEndianBinaryHelper.BufferToUint16(buf, 0);
var isGirl = ((tmpU16_0 >> 14) & 1) == 1;
var favColor = (int)((tmpU16_0 >> 1) & 0xF);
int height = buf[0x16];
Expand All @@ -89,7 +90,7 @@ private static byte[] GenerateStudioDataArray(byte[] buf)
studio[2] = (byte)weight; // Weight (mapped to index 2 in studio)

// --- Face ---
var tmpU16_20 = BigEndianBinaryReader.BufferToUint16(buf, 0x20);
var tmpU16_20 = BigEndianBinaryHelper.BufferToUint16(buf, 0x20);
var faceShape = (int)(tmpU16_20 >> 13);
var skinColor = (int)((tmpU16_20 >> 10) & 7);
var facialFeature = (int)((tmpU16_20 >> 6) & 0xF); // Note: JS uses 0xF mask here, map to makeup/wrinkles
Expand All @@ -102,7 +103,7 @@ private static byte[] GenerateStudioDataArray(byte[] buf)
studio[0x12] = (byte)makeup;

// --- Hair ---
var tmpU16_22 = BigEndianBinaryReader.BufferToUint16(buf, 0x22);
var tmpU16_22 = BigEndianBinaryHelper.BufferToUint16(buf, 0x22);
var hairStyle = (int)(tmpU16_22 >> 9);
var hairColor = (int)((tmpU16_22 >> 6) & 7);
var flipHair = (int)((tmpU16_22 >> 5) & 1);
Expand All @@ -112,7 +113,7 @@ private static byte[] GenerateStudioDataArray(byte[] buf)
studio[0x1C] = (byte)flipHair;

// --- Eyebrows ---
var tmpU32_24 = BigEndianBinaryReader.BufferToUint32(buf, 0x24);
var tmpU32_24 = BigEndianBinaryHelper.BufferToUint32(buf, 0x24);
var eyebrowStyle = (int)(tmpU32_24 >> 27);
var eyebrowRotation = (int)((tmpU32_24 >> 22) & 0xF); // Note: JS uses 0xF mask
var eyebrowColor = (int)((tmpU32_24 >> 13) & 7);
Expand All @@ -130,7 +131,7 @@ private static byte[] GenerateStudioDataArray(byte[] buf)
studio[0xF] = (byte)eyebrowXSpacing;

// --- Eyes ---
var tmpU32_28 = BigEndianBinaryReader.BufferToUint32(buf, 0x28);
var tmpU32_28 = BigEndianBinaryHelper.BufferToUint32(buf, 0x28);
var eyeStyle = (int)(tmpU32_28 >> 26);
var eyeRotation = (int)((tmpU32_28 >> 21) & 7); // Note: JS uses 7 (0b111) mask
var eyeYPosition = (int)((tmpU32_28 >> 16) & 0x1F);
Expand All @@ -149,7 +150,7 @@ private static byte[] GenerateStudioDataArray(byte[] buf)
studio[8] = (byte)eyeXSpacing;

// --- Nose ---
var tmpU16_2C = BigEndianBinaryReader.BufferToUint16(buf, 0x2C);
var tmpU16_2C = BigEndianBinaryHelper.BufferToUint16(buf, 0x2C);
var noseStyle = (int)(tmpU16_2C >> 12);
var noseScale = (int)((tmpU16_2C >> 8) & 0xF);
var noseYposition = (int)((tmpU16_2C >> 3) & 0x1F);
Expand All @@ -160,7 +161,7 @@ private static byte[] GenerateStudioDataArray(byte[] buf)
studio[0x2D] = (byte)noseYposition;

// --- Mouth ---
var tmpU16_2E = BigEndianBinaryReader.BufferToUint16(buf, 0x2E);
var tmpU16_2E = BigEndianBinaryHelper.BufferToUint16(buf, 0x2E);
var mouseStyle = (int)(tmpU16_2E >> 11);
var mouseColor = (int)((tmpU16_2E >> 9) & 3); // Lip color (0-3)
var mouseScale = (int)((tmpU16_2E >> 5) & 0xF);
Expand All @@ -174,7 +175,7 @@ private static byte[] GenerateStudioDataArray(byte[] buf)
studio[0x27] = (byte)mouseYPosition;

// --- Beard / Mustache ---
var tmpU16_32 = BigEndianBinaryReader.BufferToUint16(buf, 0x32);
var tmpU16_32 = BigEndianBinaryHelper.BufferToUint16(buf, 0x32);
var mustacheStyle = (int)(tmpU16_32 >> 14);
var beardStyle = (int)((tmpU16_32 >> 12) & 3);
var facialHairColor = (int)((tmpU16_32 >> 9) & 7);
Expand All @@ -188,7 +189,7 @@ private static byte[] GenerateStudioDataArray(byte[] buf)
studio[0x2A] = (byte)mustacheYPosition;

// --- Glasses ---
var tmpU16_30 = BigEndianBinaryReader.BufferToUint16(buf, 0x30);
var tmpU16_30 = BigEndianBinaryHelper.BufferToUint16(buf, 0x30);
var glassesStyle = (int)(tmpU16_30 >> 12);
var glassesColor = (int)((tmpU16_30 >> 9) & 7);
var glassesScale = (int)((tmpU16_30 >> 5) & 7); // Note: JS uses 7 mask
Expand All @@ -208,7 +209,7 @@ private static byte[] GenerateStudioDataArray(byte[] buf)
studio[0x1A] = (byte)glassesYPosition;

// --- Mole ---
var tmpU16_34 = BigEndianBinaryReader.BufferToUint16(buf, 0x34);
var tmpU16_34 = BigEndianBinaryHelper.BufferToUint16(buf, 0x34);
var enableMole = (int)(tmpU16_34 >> 15);
var moleScale = (int)((tmpU16_34 >> 11) & 0xF);
var moleYPosition = (int)((tmpU16_34 >> 6) & 0x1F);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using WheelWizard.Helpers;

namespace WheelWizard.Models.GameData;
namespace WheelWizard.WiiManagement.GameLicense.Domain;

public class FriendProfile : PlayerProfileBase
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace WheelWizard.Models.GameData;
namespace WheelWizard.WiiManagement.GameLicense.Domain;

public class LicenseCollection
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
namespace WheelWizard.Models.GameData;
using WheelWizard.WiiManagement.GameLicense.Domain.Statistics;

namespace WheelWizard.WiiManagement.GameLicense.Domain;

public class LicenseProfile : PlayerProfileBase
{
public required uint TotalRaceCount { get; set; }
public required uint TotalWinCount { get; set; }
public List<FriendProfile> Friends { get; set; } = [];
public LicenseStatistics Statistics { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
using WheelWizard.Helpers;
using WheelWizard.Services.LiveData;
using WheelWizard.WheelWizardData.Domain;
using WheelWizard.WiiManagement.Domain.Mii;
using WheelWizard.WiiManagement.MiiManagement.Domain.Mii;

namespace WheelWizard.Models.GameData;
namespace WheelWizard.WiiManagement.GameLicense.Domain;

public abstract class PlayerProfileBase : INotifyPropertyChanged
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace WheelWizard.WiiManagement.GameLicense.Domain.Statistics;

public class BattleCompletions
{
/// <summary>
/// Key = Battle Stage, Value = Amount of times the stage was played
/// </summary>
public Dictionary<Stage, int> Stage { get; set; } = new();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
namespace WheelWizard.WiiManagement.GameLicense.Domain.Statistics;

public enum CupTrophyType
{
Gold = 0,
Silver = 1,
Bronze = 2,
None = 3,
}

public enum CupRank
{
ThreeStars = 0,
TwoStars = 1,
OneStar = 2,
A = 3,
B = 4,
C = 5,
D = 6,
E = 7,
F = 8,
}

// The 10 battle stages in the order they appear in RKPD (0x1A6 onward).
public enum Stage : byte
{
DelfinoPier = 0,
BlockPlaza,
ChainChompWheel,
FunkyStadium,
ThwompDesert,
GCNCookieLand,
DSTwilightHouse,
SNESBattleCourse4,
GBABattleCourse3,
N64Skyscraper,
}

public enum Course : byte
{
MarioCircuit = 0,
MooMooMeadows,
MushroomGorge,
GrumbleVolcano,
ToadsFactory,
CoconutMall,
DKSummit,
WariosGoldMine,
LuigiCircuit,
DaisyCircuit,
MoonviewHighway,
MapleTreeway,
BowserCastle,
RainbowRoad,
DryDryRuins,
KoopaCape,
GCNPeachBeach,
GCNMarioCircuit,
GCNWaluigiStadium,
GCNDKMountain,
DSYoshiFalls,
DSDesertHills,
DSPeachGardens,
DSDelfinoSquare,
SNESMarioCircuit3,
SNESGhostValley2,
N64MarioRaceway,
N64SherbetLand,
N64BowsersCastle,
N64DKsJungleParkway,
GBABowserCastle3,
GBAShyGuyBeach,
}

public enum Vehicle : byte
{
StandardKartS = 0,
StandardKartM,
StandardKartL,
BoosterSeat,
ClassicDragster,
Offroader,
MiniBeast,
WildWing,
FlameFlyer,
CheepCharger,
SuperBlooper,
PiranhaProwler,
TinyTitan,
Daytripper,
Jetsetter,
BlueFalcon,
Sprinter,
Honeycoupe,
StandardBikeS,
StandardBikeM,
StandardBikeL,
BulletBike,
MachBike,
FlameRunner,
BitBike,
Sugarscoot,
WarioBike,
Quacker,
ZipZip,
ShootingStar,
Magikruiser,
Sneakster,
Spear,
JetBubble,
DolphinDasher,
Phantom,
}

// The 24 playable characters in the order they appear in RKPD (0xEC onward).
public enum Character : byte
{
Mario = 0,
BabyPeach,
Waluigi,
Bowser,
BabyDaisy,
DryBones,
BabyMario,
Luigi,
Toad,
DonkeyKong,
Yoshi,
Wario,
BabyLuigi,
Toadette,
KoopaTroopa,
Daisy,
Peach,
Birdo,
DiddyKong,
KingBoo,
BowserJr,
DryBowser,
FunkyKong,
Rosalina,
Mii = 23,
}

public enum DriftType
{
Standard = 0,
Manual = 1,
Automatic = 2,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace WheelWizard.WiiManagement.GameLicense.Domain.Statistics;

public class LicenseStatistics
{
public RaceTotals RaceTotals { get; set; } = new();
public PreferredControls Controls { get; set; } = new();
public Performance Performance { get; init; } = new();
public RaceCompletions RaceCompletions { get; init; } = new();
public PreferredControls PreferredControls { get; init; } = new();
public BattleCompletions BattleCompletions { get; init; } = new();
public ushort TotalCompetitions { get; init; }
public TrophyCabinet? Trophies { get; init; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace WheelWizard.WiiManagement.GameLicense.Domain.Statistics;

public class Performance
{
public int TricksPerformed { get; set; } // total amount of tricks performed
public int ItemHitsDealt { get; set; } // total amount of item hits dealt
public int ItemHitsReceived { get; set; } // total amount of item hits received
public int FirstPlaces { get; set; } // total amount of first places achieved
public float DistanceTotal { get; set; } // Total Distance driven
public float DistanceInFirstPlace { get; set; } // Total Distance driven in first place
public float DistanceVsRaces { get; set; }

// percentage of time in 1st = floor(DistanceInFirstPlace / DistanceVsRaces * 100).

public int PercentTimeInFirstPlace
{
get
{
if (DistanceVsRaces == 0)
return 0;

return (int)Math.Floor(DistanceInFirstPlace / DistanceVsRaces * 100);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace WheelWizard.WiiManagement.GameLicense.Domain.Statistics;

public class PreferredControls
{
public int WiiWheelRaces { get; set; } // amount of matched played with the Wii Wheel
public int WiiWheelBattles { get; set; } // amount of matched played with the Wii Wheel in battles
public float WheelWheelUsageRatio
{
get
{
if (WiiWheelRaces + WiiWheelBattles == 0)
return 0f;

return (float)WiiWheelRaces / (WiiWheelRaces + WiiWheelBattles);
}
}
public DriftType PreferredDriftType { get; set; } = DriftType.Standard; // preferred drift type, default is standard
}
Loading
Loading