TL866/InfoIcDump/Infoic.cs
2025-06-04 07:22:09 +03:00

1594 lines
65 KiB
C#

using System.Runtime.InteropServices;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace InfoIcDump
{
internal class Infoic
{
//System API
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void FreeLibrary(IntPtr module);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr module, string proc);
// Function pointers delegates
private delegate void DGetMfcStru76(uint manufacturer, ref MfcStruct mfstruct);
private delegate void DGetIcStru76(uint manufacturer, uint device_index, ref InfoIc2Struct devstruct);
private delegate uint DGetIcMFC76(string search, uint[] manufacturer_array, uint type, uint mask);
private delegate uint DGetIcList76(string search, uint[] ic_array, uint manufacturer, uint type, uint mask);
private delegate uint DGetDllInfo76(ref uint dll_version, ref uint num_mfcs, uint version);
private delegate void DGetMfcStru2(uint manufacturer, ref MfcStruct mfstruct);
private delegate void DGetIcStru2(uint manufacturer, uint device_index, ref InfoIc2Struct devstruct);
private delegate uint DGetIcMFC2(string search, uint[] manufacturer_array, uint type, uint mask);
private delegate uint DGetIcList2(string search, uint[] ic_array, uint manufacturer, uint type, uint mask);
private delegate uint DGetDllInfo2(ref uint dll_version, ref uint num_mfcs, uint version);
private delegate void DGetMfcStru(uint manufacturer, ref MfcStruct mfstruct);
private delegate void DGetIcStru(uint manufacturer, uint device_index, ref InfoIcStruct devstruct);
private delegate uint DGetIcMFC(string search, uint[] manufacturer_array, uint type);
private delegate uint DGetIcList(string search, uint[] ic_array, uint Manuf, uint type);
private delegate uint DGetDllInfo(ref uint dll_version, ref uint num_mfcs);
private readonly DGetMfcStru? GetMfcStruct;
private readonly DGetIcStru? GetIcStruct;
private readonly DGetIcMFC? GetIcMFC;
private readonly DGetIcList? GetIcList;
private readonly DGetDllInfo? GetDllInfo;
private readonly DGetMfcStru2? GetMfcStruct2;
private readonly DGetIcStru2? GetIcStruct2;
private readonly DGetIcMFC2? GetIcMFC2;
private readonly DGetIcList2? GetIcList2;
private readonly DGetDllInfo2? GetDllInfo2;
private readonly DGetMfcStru76? GetMfcStruct76;
private readonly DGetIcStru76? GetIcStruct76;
private readonly DGetIcMFC76? GetIcMFC76;
private readonly DGetIcList76? GetIcList76;
private readonly DGetDllInfo76? GetDllInfo76;
public struct DevStruct
{
public uint ProtocolId;
public uint Opts8;
public uint Category;
public string Name;
public uint Variant;
public uint CodeMemorySize;
public uint DataMemorySize;
public uint DataMemory2Size;
public uint Opts7;
public uint ReadBufferSize;
public uint WriteBufferSize;
public uint Opts1;
public uint Opts2;
public uint Opts3;
public ulong ChipId;
public uint Opts5;
public uint ChipIdBytesCount;
public uint Opts6;
public uint PackageDetails;
public uint Opts4;
public string config;
}
// InfoIc device structure
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
private struct InfoIcStruct
{
public uint ProtocolId;
public uint Opts8;
public uint Category;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
public string Name;
public uint Variant;
public uint CodeMemorySize;
public uint DataMemorySize;
public uint DataMemory2Size;
public ushort Opts7;
public ushort ReadBufferSize;
public ushort WriteBufferSize;
public ushort Opts1;
public uint Opts2;
public uint Opts3;
public uint ChipId;
public uint Opts5;
public uint ChipIdBytesCount;
public uint Opts6;
public uint PackageDetails;
public uint Opts4;
}//108 bytes
// InfoIc2Plus device structure
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
private struct InfoIc2Struct
{
public uint ProtocolId;
public uint Opts8;
public uint Category;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
public string Name;
public uint Variant;
public uint CodeMemorySize;
public uint DataMemorySize;
public uint DataMemory2Size;
public uint Opts7;
public ushort ReadBufferSize;
public ushort WriteBufferSize;
public uint Opts5;
public uint Opts1;
public uint Opts2;
public uint Opts3;
public ulong ChipId;
public uint ChipIdBytesCount;
public uint Opts6;
public uint PackageDetails;
public uint Opts4;
}//116 bytes
// Manufacturer structure
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
private struct MfcStruct
{
public uint Manufacturer;
public uint Icon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string ManufacturerName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
public string ManufacturerDescription;
public IntPtr Devices;
public uint Count;
}
public static readonly uint T56_MASK = 0x10000000;
public static readonly uint T48_MASK = 0x40000000;
public static readonly uint TL866II_MASK = 0x20000000;
public static readonly uint SMT_FLAG = 0x80000000;
public static readonly uint PLCC_FLAG = 0x40000000;
public static readonly uint ERASE_FLAG = 0x20;
public enum CHIP_TYPE : uint { MEMORY = 1, MPU, PLD, SRAM, LOGIC, NAND, EMMC, VGA }
public enum DB_TYPE { INFOIC, INFOIC2, INFOIC76 }
private readonly IntPtr HInfoIc = IntPtr.Zero;
private readonly IntPtr HInfoIc2 = IntPtr.Zero;
private readonly IntPtr HInfoIc76 = IntPtr.Zero;
private readonly uint InfoicDeviceCount;
private readonly uint Infoic2DeviceCount;
private readonly uint Infoic76DeviceCount;
private readonly uint InfoicManufCount;
private readonly uint Infoic2ManufCount;
private readonly uint Infoic76ManufCount;
public bool InfoIcLoaded { get => HInfoIc != IntPtr.Zero; }
public bool InfoIc2Loaded { get => HInfoIc2 != IntPtr.Zero; }
public bool InfoIc76Loaded { get => HInfoIc76 != IntPtr.Zero; }
public uint InfoIcNumDevices { get => InfoicDeviceCount; }
public uint InfoIc2NumDevices { get => Infoic2DeviceCount; }
public uint InfoIc76NumDevices { get => Infoic76DeviceCount; }
public uint InfoIcManufacturers { get => InfoicManufCount; }
public uint InfoIc2Manufacturers { get => Infoic2ManufCount; }
public uint InfoIc76Manufacturers { get => Infoic76ManufCount; }
private static IntPtr GetProc(ref IntPtr handle, string name)
{
IntPtr ProcAddress = GetProcAddress(handle, name);
if (ProcAddress == IntPtr.Zero)
{
FreeLibrary(handle);
handle = IntPtr.Zero;
}
return ProcAddress;
}
// Class constructor
public Infoic(string InfoicPath, string Infoic2Path, string Infoic76Path)
{
// Try to load modules
if (InfoicPath != string.Empty) { HInfoIc = LoadLibrary(InfoicPath); }
if (Infoic2Path != string.Empty) { HInfoIc2 = LoadLibrary(Infoic2Path); }
if (Infoic76Path != string.Empty) { HInfoIc76 = LoadLibrary(Infoic76Path); }
IntPtr ProcAddress;
if (HInfoIc != IntPtr.Zero)
{
ProcAddress = GetProc(ref HInfoIc, "GetMfcStru");
if (ProcAddress == IntPtr.Zero) { return; }
GetMfcStruct = (DGetMfcStru)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetMfcStru));
ProcAddress = GetProc(ref HInfoIc, "GetIcStru");
if (ProcAddress == IntPtr.Zero) { return; }
GetIcStruct = (DGetIcStru)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetIcStru));
ProcAddress = GetProc(ref HInfoIc, "GetIcMFC");
if (ProcAddress == IntPtr.Zero) { return; }
GetIcMFC = (DGetIcMFC)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetIcMFC));
ProcAddress = GetProc(ref HInfoIc, "GetIcList");
if (ProcAddress == IntPtr.Zero) { return; }
GetIcList = (DGetIcList)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetIcList));
ProcAddress = GetProc(ref HInfoIc, "GetDllInfo");
if (ProcAddress == IntPtr.Zero) { return; }
GetDllInfo = (DGetDllInfo)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetDllInfo));
InfoicDeviceCount = GetDeviceCount(ref InfoicManufCount, DB_TYPE.INFOIC);
if (InfoicDeviceCount == 0)
{
FreeLibrary(HInfoIc);
HInfoIc = IntPtr.Zero;
}
}
if (HInfoIc2 != IntPtr.Zero)
{
ProcAddress = GetProc(ref HInfoIc2, "GetMfcStru");
if (ProcAddress == IntPtr.Zero) { return; }
GetMfcStruct2 = (DGetMfcStru2)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetMfcStru2));
ProcAddress = GetProc(ref HInfoIc2, "GetIcStru");
if (ProcAddress == IntPtr.Zero) { return; }
GetIcStruct2 = (DGetIcStru2)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetIcStru2));
ProcAddress = GetProc(ref HInfoIc2, "GetIcMFC");
if (ProcAddress == IntPtr.Zero) { return; }
GetIcMFC2 = (DGetIcMFC2)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetIcMFC2));
ProcAddress = GetProc(ref HInfoIc2, "GetIcList");
if (ProcAddress == IntPtr.Zero) { return; }
GetIcList2 = (DGetIcList2)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetIcList2));
ProcAddress = GetProc(ref HInfoIc2, "GetDllInfo");
if (ProcAddress == IntPtr.Zero) { return; }
GetDllInfo2 = (DGetDllInfo2)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetDllInfo2));
Infoic2DeviceCount = GetDeviceCount(ref Infoic2ManufCount, DB_TYPE.INFOIC2);
if (Infoic2DeviceCount == 0)
{
FreeLibrary(HInfoIc2);
HInfoIc2 = IntPtr.Zero;
}
}
if (HInfoIc76 != IntPtr.Zero)
{
ProcAddress = GetProc(ref HInfoIc76, "GetMfcStru");
if (ProcAddress == IntPtr.Zero) { return; }
GetMfcStruct76 = (DGetMfcStru76)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetMfcStru76));
ProcAddress = GetProc(ref HInfoIc76, "GetIcStru");
if (ProcAddress == IntPtr.Zero) { return; }
GetIcStruct76 = (DGetIcStru76)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetIcStru76));
ProcAddress = GetProc(ref HInfoIc76, "GetIcMFC");
if (ProcAddress == IntPtr.Zero) { return; }
GetIcMFC76 = (DGetIcMFC76)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetIcMFC76));
ProcAddress = GetProc(ref HInfoIc76, "GetIcList");
if (ProcAddress == IntPtr.Zero) { return; }
GetIcList76 = (DGetIcList76)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetIcList76));
ProcAddress = GetProc(ref HInfoIc76, "GetDllInfo");
if (ProcAddress == IntPtr.Zero) { return; }
GetDllInfo76 = (DGetDllInfo76)Marshal.GetDelegateForFunctionPointer(ProcAddress, typeof(DGetDllInfo76));
Infoic76DeviceCount = GetDeviceCount(ref Infoic76ManufCount, DB_TYPE.INFOIC76);
if (Infoic76DeviceCount == 0)
{
FreeLibrary(HInfoIc76);
HInfoIc76 = IntPtr.Zero;
}
}
}
private void GetMfc(uint manufacturer, ref MfcStruct mfcstruct, DB_TYPE type)
{
if (type == DB_TYPE.INFOIC)
{
if (GetMfcStruct is not null)
{
GetMfcStruct(manufacturer, ref mfcstruct);
}
}
else if (type == DB_TYPE.INFOIC2)
{
if (GetMfcStruct2 is not null)
{
GetMfcStruct2(manufacturer, ref mfcstruct);
}
}
else
{
if (GetMfcStruct76 is not null)
{
GetMfcStruct76(manufacturer, ref mfcstruct);
}
}
}
public uint GetMfcDevices(uint manufacturer, DB_TYPE type)
{
MfcStruct mfcstruct = new();
GetMfc(manufacturer, ref mfcstruct, type);
return mfcstruct.Count;
}
public string GetManufName(uint manufacturer, DB_TYPE type)
{
MfcStruct mfcstruct = new();
GetMfc(manufacturer, ref mfcstruct, type);
return mfcstruct.ManufacturerName;
}
public DevStruct GetDevice(uint manufacturer, uint index, DB_TYPE type)
{
DevStruct devstruct = new();
if (type == DB_TYPE.INFOIC)
{
if (GetIcStruct is null) { return devstruct; }
InfoIcStruct device = new();
device.Name = string.Empty;
GetIcStruct(manufacturer, index, ref device);
devstruct.ProtocolId = device.ProtocolId;
devstruct.Opts8 = device.Opts8;
devstruct.Category = device.Category;
devstruct.Name = device.Name;
devstruct.Variant = device.Variant;
devstruct.CodeMemorySize = device.CodeMemorySize;
devstruct.DataMemorySize = device.DataMemorySize;
devstruct.DataMemory2Size = device.DataMemory2Size;
devstruct.Opts7 = device.Opts7;
devstruct.ReadBufferSize = device.ReadBufferSize;
devstruct.WriteBufferSize = device.WriteBufferSize;
devstruct.Opts1 = device.Opts1;
devstruct.Opts2 = device.Opts2;
devstruct.Opts3 = device.Opts3;
devstruct.ChipId = device.ChipId;
devstruct.Opts5 = device.Opts5;
devstruct.ChipIdBytesCount = device.ChipIdBytesCount;
devstruct.Opts6 = device.Opts6;
devstruct.PackageDetails = device.PackageDetails;
devstruct.Opts4 = device.Opts4;
}
else if (type == DB_TYPE.INFOIC2)
{
if (GetIcStruct2 is null) { return devstruct; }
InfoIc2Struct device = new();
device.Name = string.Empty;
GetIcStruct2(manufacturer, index, ref device);
devstruct.ProtocolId = device.ProtocolId;
devstruct.Opts8 = device.Opts8;
devstruct.Category = device.Category;
devstruct.Name = device.Name;
devstruct.Variant = device.Variant;
devstruct.CodeMemorySize = device.CodeMemorySize;
devstruct.DataMemorySize = device.DataMemorySize;
devstruct.DataMemory2Size = device.DataMemory2Size;
devstruct.Opts7 = device.Opts7;
devstruct.ReadBufferSize = device.ReadBufferSize;
devstruct.WriteBufferSize = device.WriteBufferSize;
devstruct.Opts1 = device.Opts1;
devstruct.Opts2 = device.Opts2;
devstruct.Opts3 = device.Opts3;
devstruct.ChipId = device.ChipId;
devstruct.Opts5 = device.Opts5;
devstruct.ChipIdBytesCount = device.ChipIdBytesCount;
devstruct.Opts6 = device.Opts6;
devstruct.PackageDetails = device.PackageDetails;
devstruct.Opts4 = device.Opts4;
}
else
{
if (GetIcStruct76 is null) { return devstruct; }
InfoIc2Struct device = new();
device.Name = string.Empty;
GetIcStruct76(manufacturer, index, ref device);
devstruct.ProtocolId = device.ProtocolId;
devstruct.Opts8 = device.Opts8;
devstruct.Category = device.Category;
devstruct.Name = device.Name;
devstruct.Variant = device.Variant;
devstruct.CodeMemorySize = device.CodeMemorySize;
devstruct.DataMemorySize = device.DataMemorySize;
devstruct.DataMemory2Size = device.DataMemory2Size;
devstruct.Opts7 = device.Opts7;
devstruct.ReadBufferSize = device.ReadBufferSize;
devstruct.WriteBufferSize = device.WriteBufferSize;
devstruct.Opts1 = device.Opts1;
devstruct.Opts2 = device.Opts2;
devstruct.Opts3 = device.Opts3;
devstruct.ChipId = device.ChipId;
devstruct.Opts5 = device.Opts5;
devstruct.ChipIdBytesCount = device.ChipIdBytesCount;
devstruct.Opts6 = device.Opts6;
devstruct.PackageDetails = device.PackageDetails;
devstruct.Opts4 = device.Opts4;
}
// Fix bad endiannes in database
devstruct.ChipId = ToLittleEndian(devstruct.ChipId, devstruct.ChipIdBytesCount);
// Patch opts8 and package_details
if (type != DB_TYPE.INFOIC)
{
PatchDevice(ref devstruct);
}
return devstruct;
}
private uint GetDeviceCount(ref uint manuf_count, DB_TYPE type)
{
uint count = 0;
uint dll_version = 0;
// Get dll info
if (type == DB_TYPE.INFOIC)
{
if (GetDllInfo is null) { return 0; }
GetDllInfo(ref dll_version, ref manuf_count);
if (manuf_count > 136) { return 0; }
}
else if (type == DB_TYPE.INFOIC2)
{
if (GetDllInfo2 is null) { return 0; }
GetDllInfo2(ref dll_version, ref manuf_count, 0);
if (manuf_count < 139) { return 0; }
}
else
{
if (GetDllInfo76 is null) { return 0; }
GetDllInfo76(ref dll_version, ref manuf_count, 0);
if (manuf_count < 170) { return 0; }
}
//Iterate over the entire manufacturers and count all devices
for (uint i = 0; i < manuf_count; i++)
{
MfcStruct mfcstruct = new();
if (type == DB_TYPE.INFOIC)
{
if (GetMfcStruct is null) { return 0; }
GetMfcStruct(i, ref mfcstruct);
}
else if (type == DB_TYPE.INFOIC2)
{
if (GetMfcStruct2 is null) { return 0; }
GetMfcStruct2(i, ref mfcstruct);
}
else if (type == DB_TYPE.INFOIC76)
{
if (GetMfcStruct76 is null) { return 0; }
GetMfcStruct76(i, ref mfcstruct);
}
count += mfcstruct.Count;
}
return count;
}
private ulong ToLittleEndian(ulong value, uint size)
{
if (value == 0 || size == 0) return 0;// This is a database bug. Size is zero and id garbage bytes
return ((0xFF) & (value >> 56) | (0xFF00) & (value >> 40) | (0xFF0000) & (value >> 24) | (0xFF000000) & (value >> 8) |
(0xFF00000000) & (value << 8) | (0xFF0000000000) & (value << 24) | (0xFF000000000000) & (value << 40) |
(0xFF00000000000000) & (value << 56)) >> (int)(8 * (8 - size));
}
private void PatchDevice(ref DevStruct Device)
{
// Patch package details
PatchPackage(ref Device);
// Patch Opts5
if (Device.Opts7 == 0x06 && Device.Opts5 >= 0xF0)
{
Device.Opts5 = 0xF0;
}
Device.Opts5 = (Device.Opts5 & 0xFFFF00FF) | (Device.Opts1 << 8);
// Patch Opts8
uint lo8 = PatchLo8(ref Device);
uint hi8 = PatchHi8(ref Device);
Device.Opts8 = (Device.Opts8 & 0xFFFF0000) | (hi8 << 8) | lo8;
// Patch variant high byte
if((Device.Variant & 0xFF00) == 0)
{
uint algo = GetAlgoNumber(Device);
Device.Variant = (Device.Variant & 0x00FF) | (algo << 8);
}
}
private static byte GetAlgoNumber(DevStruct device)
{
byte variantLoByte = (byte)(device.Variant & 0xFF);
byte voltagesHiByte = (byte)((device.Opts5 >> 8) & 0xFF);
switch (device.ProtocolId)
{
case 0x01:
if ((variantLoByte & 3) == 1)
{
if (device.CodeMemorySize < 0x8000)
return 0x1A;
return 0x11;
}
if ((variantLoByte & 3) == 0)
return 0x13;
if ((variantLoByte & 3) == 2)
return 0x14;
return (byte)(variantLoByte & 3);
case 0x02:
if (variantLoByte >= 0)
{
if ((voltagesHiByte & 0xF) != 2)
return 0x21;
return 0x2A;
}
else if ((variantLoByte & 0x20) != 0)
{
if ((voltagesHiByte & 0xF) == 1)
{
return 0x69;
}
else if ((voltagesHiByte & 0xF) == 2)
{
return 0x68;
}
else
{
return 0x67;
}
}
else if ((voltagesHiByte & 0xF) == 1)
{
return 0x2B;
}
else
{
if ((voltagesHiByte & 0xF) != 2)
return 0x11;
return 0x1A;
}
case 0x03:
case 0x0F:
if ((variantLoByte & 0xF0) == 32)
{
if ((variantLoByte & 3) == 3)
{
return 0x20;
}
else if ((variantLoByte & 3) == 2)
{
return 0x21;
}
}
else
{
switch (variantLoByte & 3)
{
case 3:
return 0x10;
case 2:
return 0x11;
case 1:
return 0x12;
default:
if ((variantLoByte & 3) == 0)
return 0x13;
break;
}
}
return (byte)(variantLoByte & 0xF0);
case 0x05:
if (device.PackageDetails == 5)
return 0x76;
else
return 0x75;
case 0x06:
if ((variantLoByte & 0x80) != 0)
{
if (device.PackageDetails == 5)
return 0x73;
return 0x71;
}
if (device.PackageDetails == 5)
{
return 0x72;
}
else
{
if (device.CodeMemorySize != 0x80000)
return 0x71;
return 0x70;
}
case 0x07:
if ((variantLoByte & 0x10) != 0)
{
if (device.CodeMemorySize == 0x10000)
{
return 0x31;
}
else if (device.CodeMemorySize == 0x8000)
{
return 0x32;
}
else
{
return 0x33;
}
}
else
{
return 0x41;
}
case 0x08:
if (device.PackageDetails == 5)
{
if (variantLoByte == 4)
{
return 0x22;
}
else if (variantLoByte == 3)
{
return 0x23;
}
else
{
if (variantLoByte != 2)
return 0x21;
return 0x24;
}
}
else
{
if (variantLoByte == 4)
return 0x12;
if (variantLoByte == 3)
return 0x13;
if (variantLoByte != 2)
return 0x11;
return 0x14;
}
case 0x09:
if (device.PackageDetails == 0x28000000)
{
if (device.CodeMemorySize != 0x80000)
return 0x1A;
return 0x2A;
}
if (device.PackageDetails == 0xFD000000)
{
if (device.CodeMemorySize == 0x80000)
return 0x2B;
return 0x1B;
}
else if (device.PackageDetails == 4)
{
if (device.CodeMemorySize == 0x80000)
return 0x2C;
else
return 0x1C;
}
return (byte)device.PackageDetails;
case 0x0A:
if ((variantLoByte & 0x80) != 0)
{
return 0x42;
}
else if (device.CodeMemorySize == 0x10000)
{
return 0x34;
}
else if (device.CodeMemorySize == 0x8000)
{
return 0x35;
}
else
{
return 0x36;
}
case 0x0B:
if ((variantLoByte & 0x10) != 0)
{
return 0x43;
}
else if (device.CodeMemorySize == 0x800)
{
return 0x3B;
}
else
{
return 0x3A;
}
case 0x0D:
if (device.PackageDetails == 5)
return 0x45;
else
return 0x44;
case 0x0E:
return 0x50;
case 0x10:
if (variantLoByte == 16 || variantLoByte == 17)
{
if (device.PackageDetails == 5)
return 0x7E;
else
return 0x7B;
}
else if (variantLoByte == 18)
{
if (device.PackageDetails == 5)
return 0x7F;
else
return 0x7C;
}
else if (device.PackageDetails == 5)
{
return 0x7D;
}
else
{
return 0x7A;
}
case 0x11:
if (device.PackageDetails == 5)
{
if ((variantLoByte & 0xF) == 1)
return 0x92;
else
return 0x94;
}
else if (device.PackageDetails == 3)
{
if ((variantLoByte & 0xF) == 1)
return 0x95;
else
return 0x96;
}
else if ((variantLoByte & 0xF) == 1)
{
return 0x91;
}
else
{
return 0x93;
}
default:
return 0x00;
}
}
// Patch PackageDetails and Opts4
private static void PatchPackage(ref DevStruct Device)
{
if (Device.ProtocolId == 0x2D) return;
if (Device.ProtocolId == 3)
{
Device.Opts4 |= 0x100048;
if ((Device.PackageDetails & 0xFF00) == 0x500) return;
Device.PackageDetails |= 0x900;
return;
}
else
{
if (Device.ProtocolId == 2)
{
if ((Device.Variant & 0x20) != 0) return;
Device.Opts4 |= 0x100000;
Device.PackageDetails |= 0xA00;
return;
}
else
{
if (Device.ProtocolId != 1 || (byte)Device.Opts1 != 0) return;
Device.Opts4 |= 0x100000;
Device.PackageDetails |= 0xB00;
}
}
}
// Patch Opts8 hibyte
private static byte PatchHi8(ref DevStruct Device)
{
byte Opts8Hibyte = (byte)(Device.Opts8 >> 8);
byte Opts5Hibyte = (byte)(Device.Opts5 >> 8);
// Opts8HiByte != 0
if (Opts8Hibyte != 0x00)
{
if (Opts8Hibyte == 0xFF)
{
return 0x00;
}
return Opts8Hibyte;
}
// Opts8HiByte == 0
switch (Device.ProtocolId)
{
case 0x01:
return 0x80;
case 0x02:
switch (Opts5Hibyte & 0x0F)
{
case 0x01:
return 0x7F;
case 0x02:
return 0x7E;
default:
return 0x7D;
}
case 0x03:
case 0x0F:
return (byte)((Device.Variant & 0xF0) == 0x20 ? 0x15 : 0x03);
case 0x04:
return 0x03;
case 0x05:
switch (Device.PackageDetails)
{
case 0x20000000:
case 0xA0000000:
case 0xFF000000:
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x17;
case 0x20000:
return 0x18;
case 0x40000:
return 0x19;
case 0x80000:
return 0x1A;
default:
return 0x16;
}
default:
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x1C;
case 0x20000:
return 0x1D;
case 0x40000:
return 0x1E;
case 0x80000:
return 0x1F;
default:
return 0x1B;
}
}
case 0x06:
if ((Device.Variant & 0x80) == 0x00)
{
if (Device.PackageDetails == 0x20000000 ||
Device.PackageDetails == 0xA0000000 ||
Device.PackageDetails == 0xFF000000)
{
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x59;
case 0x20000:
return 0x5A;
case 0x40000:
return 0x5B;
case 0x80000:
return 0x5C;
}
}
else
{
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x62;
case 0x20000:
return 0x63;
case 0x40000:
return 0x64;
case 0x80000:
return 0x65;
}
}
}
else
{
if (Device.PackageDetails == 0x20000000 ||
Device.PackageDetails == 0xA0000000 ||
Device.PackageDetails == 0xFF000000)
{
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x5E;
case 0x20000:
return 0x5F;
case 0x40000:
return 0x60;
default:
return 0x5D;
}
}
else
{
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x67;
case 0x20000:
return 0x68;
case 0x40000:
return 0x69;
default:
return 0x66;
}
}
}
break;
case 0x07:
if ((Device.Variant & 0x20) == 0x00)
{
if (Device.CodeMemorySize == 0x2000)
{
return 0x6F;
}
return 0x0C;
}
else
{
if (Device.CodeMemorySize == 0x800)
{
return 0x71;
}
if (Device.CodeMemorySize == 0x2000)
{
return 0x70;
}
return 0x0C;
}
case 0x08:
switch (Device.Variant)
{
case 0x04:
switch (Device.PackageDetails)
{
case 0x05:
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x62;
case 0x20000:
return 0x63;
case 0x80000:
return 0x65;
default:
return 0x64;
}
default:
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x59;
case 0x20000:
return 0x5A;
case 0x80000:
return 0x5C;
default:
return 0x5B;
}
}
default:
switch (Device.PackageDetails)
{
case 0x05:
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x67;
case 0x20000:
return 0x68;
default:
return 0x69;
}
default:
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x5E;
case 0x20000:
return 0x5F;
default:
return 0x60;
}
}
}
case 0x09:
switch (Device.PackageDetails)
{
case 4:
return (byte)(Device.CodeMemorySize == 0x20000 ? 0x79 : 0x0F);
case 0xFD000000:
return (byte)(Device.CodeMemorySize == 0x20000 ? 0x7A : 0x7B);
case 0x2A000000:
return (byte)(Device.CodeMemorySize == 0x100000 ? 0x7C : 0x10);
case 2:
return 0x7C;
default:
return (byte)(Device.CodeMemorySize == 0x20000 ? 0x78 : 0x0F);
}
case 0x0A:
return (byte)((Device.Variant & 0x80) != 0x00 ? 0x75 : (Device.Variant != 0 ? 0x77 : 0x76));
case 0x0B:
case 0x2B:
case 0x2C:
return 0x0B;
case 0x0D:
switch (Device.CodeMemorySize)
{
case 0x20000:
return (byte)(Device.PackageDetails == 5 ? 0x63 : 0x5A);
case 0x40000:
return (byte)(Device.PackageDetails == 5 ? 0x64 : 0x5B);
default:
return 0x0D;
}
case 0x10:
if (Device.Variant == 0x10 || Device.Variant == 0x11 || Device.Variant == 0x12)
{
return 0x0D;
}
else if (Device.PackageDetails == 0x20000000 || Device.PackageDetails == 0xA0000000 || Device.PackageDetails == 0xFF000000)
{
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x5E;
case 0x20000:
return 0x5F;
case 0x40000:
return 0x60;
default:
return 0x5D;
}
}
else
{
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x67;
case 0x20000:
return 0x68;
case 0x40000:
return 0x69;
default:
return 0x66;
}
}
case 0x11:
if (Device.PackageDetails == 0x20000000 ||
Device.PackageDetails == 0xA0000000 ||
Device.PackageDetails == 0xFF000000)
{
if (Opts5Hibyte == 0x01)
{
return 0x6E;
}
else if ((Device.Variant & 0x80) != 0x00)
{
return 0x6A;
}
else
{
return 0x6B;
}
}
else
{
if (Opts5Hibyte == 0x01)
{
return 0x6E;
}
else if ((Device.Variant & 0x80) != 0x00)
{
return 0x6C;
}
else
{
return 0x6D;
}
}
case 0x12:
switch ((byte)Device.PackageDetails)
{
case 0x02:
switch (Device.CodeMemorySize)
{
case 0x40000:
return 0x2B;
case 0x80000:
return 0x2C;
case 0x100000:
return 0x2D;
case 0x200000:
return 0x2E;
default:
return 0x2A;
}
case 0x01:
switch (Device.CodeMemorySize)
{
case 0x100000:
return 0x26;
case 0x200000:
return 0x27;
case 0x400000:
return 0x28;
case 0x800000:
return 0x29;
default:
if (Device.CodeMemorySize == 0x40000)
{
return 0x24;
}
if (Device.CodeMemorySize == 0x80000)
{
return 0x25;
}
return 0x23;
}
case 0x0B:
return 0x14;
default:
if ((Device.PackageDetails & 0xFF000000) == 0xE1000000)
{
switch (Device.CodeMemorySize)
{
case 0x100000:
return 0x32;
case 0x200000:
return 0x33;
case 0x400000:
return 0x34;
case 0x800000:
return 0x35;
case 0x20000:
return 0x2F;
case 0x40000:
return 0x30;
case 0x80000:
return 0x31;
}
}
return 0x12;
}
case 0x13:
byte vr2 = (byte)(Device.Variant & 0xF0);
if (Opts5Hibyte == 0x00)
{
if (vr2 == 0x20 || vr2 == 0x40)
{
Dictionary<uint, byte> map = new() { { 0x40000, 0x54 }, { 0x80000, 0x54 },
{ 0x100000, 0x55 }, { 0x200000, 0x56 }, { 0x400000, 0x57 } };
return (byte)(map.ContainsKey(Device.CodeMemorySize) ? map[Device.CodeMemorySize] : 0x00);
}
else
{
Dictionary<uint, byte> map = new() { { 0x100000, 0x51 }, { 0x200000, 0x52 }, { 0x400000, 0x53 } };
return (byte)(map.ContainsKey(Device.CodeMemorySize) ? map[Device.CodeMemorySize] : 0x50);
}
}
else
{
if (vr2 == 0x10)
{
Dictionary<uint, byte> map = new() { { 0x40000, 0x46 }, { 0x80000, 0x47 }, { 0x100000, 0x48 },
{ 0x200000, 0x49 }, { 0x400000, 0x4A } };
return (byte)(map.ContainsKey(Device.CodeMemorySize) ? map[Device.CodeMemorySize] : 0x00);
}
else if (vr2 == 0x30)
{
Dictionary<uint, byte> map = new(){{ 0x40000, 0x4B },{ 0x80000, 0x4C }, { 0x100000, 0x4D },
{ 0x200000, 0x4E },{ 0x400000, 0x4F }};
return (byte)(map.ContainsKey(Device.CodeMemorySize) ? map[Device.CodeMemorySize] : 0x00);
}
else
{
Dictionary<uint, byte> map = new() { { 0x80000, 0x42 }, { 0x100000, 0x43 }, { 0x200000, 0x44 }, { 0x400000, 0x45 } };
return (byte)(map.ContainsKey(Device.CodeMemorySize) ? map[Device.CodeMemorySize] : 0x41);
}
}
case 0x14:
return 0x3F;
case 0x15:
return 0x3E;
case 0x18:
case 0x19:
case 0x1A:
case 0x1B:
Dictionary<uint, uint> table = new() { { 0xE000000, 0x06 }, { 0x8000000, 0x03 }, { 0x12000000, 0x08 },
{ 0x14000000, 0x09 }, { 0x1c000000, 0x37 }, { 0x94000000, 0x09 }, { 0x8E000000, 0x06 }, { 0x28000000, 0x39 }, { 0x88000000, 0x03 },
{ 0x92000000, 0x08 }, { 0xFA000000, 0x3B }, { 0x9C000000, 0x37 }, { 0xF9000000, 0x3A }, { 0xFB000000, 0x38 } };
return (byte)(table.ContainsKey(Device.PackageDetails & 0xFF000000) ? table[Device.PackageDetails & 0xFF000000] : 0);
case 0x1C:
return 0x74;
case 0x1D:
if ((byte)Device.PackageDetails == 0x07)
{
return 0x14;
}
else
{
switch (Device.Variant & 0xE0)
{
case 0x20:
case 0x40:
return 0x0F;
case 0x60:
return 0x09;
default:
return 0x03;
}
}
case 0x1E:
return (byte)((Device.Variant & 0x02) == 0x00 ? 0x03 : 0x06);
case 0x1F:
case 0x20:
case 0x2A:
return 0x09;
case 0x21:
case 0x22:
case 0x23:
case 0x24:
case 0x25:
case 0x26:
return 0x11;
case 0x2D:
return 0x81;
}
return Opts8Hibyte;
}
// Patch opts8_lobyte
private static byte PatchLo8(ref DevStruct Device)
{
byte Opts8Lobyte = (byte)Device.Opts8;
byte Opts5Hibyte = (byte)(Device.Opts5 >> 0x08);
// Opts8HiByte != 0
if (Opts8Lobyte != 0)
{
if (Opts8Lobyte == 0x4)
{
return 0x00;
}
return Opts8Lobyte;
}
// Opts8LoByte == 0
switch (Device.ProtocolId)
{
case 0x01:
return 0x6B;
case 0x02:
if ((Opts5Hibyte & 0x0F) == 0x01)
{
return 0x6E;
}
else
{
return (byte)(((Opts5Hibyte & 0xF) == 0x02) ? 0x6D : 0x6C);
}
case 0x04:
return 0x71;
case 0x03:
case 0x0F:
switch (Device.Variant & 0xF0)
{
case 0x20:
return 0x03;
case 0x10:
return (byte)(Opts8Lobyte + 0x02);
default:
return (byte)(Opts8Lobyte + 0x01);
}
case 0x06:
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x7;
case 0x20000:
return (byte)((Device.Variant & 0x80) == 0x0 ? 0x09 : 0x0A);
case 0x40000:
return (byte)((Device.Variant & 0x80) == 0x0 ? 0x0B : 0x0C);
case 0x80000:
return 0x0D;
}
break;
case 0x07:
if ((Device.Variant & 0x20) != 0x00)
{
switch (Device.CodeMemorySize)
{
case 0x8000:
return 0x14;
case 0x2000:
return 0x13;
default:
return 0x12;
}
}
else
{
return (byte)(Device.CodeMemorySize == 0x2000 ? 0x15 : 0x16);
}
case 0x08:
switch (Device.Variant)
{
case 0x00:
return 0x0A;
case 0x04:
switch (Device.CodeMemorySize)
{
case 0x10000:
return 0x07;
case 0x20000:
return 0x09;
default:
return 0x0D;
}
default:
return 0x0C;
}
case 0x09:
return (byte)((Device.Variant == 0x00) ? 0x18 : 0x19);
case 0x0A:
if ((Device.Variant & 0x80) == 0)
{
return (byte)(Device.Variant == 0x00 ? 0x1E : 0x1F);
}
else
{
return 0x1A;
}
case 0x0B:
return 0x17;
case 0x0D:
switch (Device.CodeMemorySize)
{
case 0x20000:
return 0x09;
case 0x40000:
return 0x0B;
case 0x80000:
return 0x0D;
default:
return 0x09;
}
case 0x10:
switch (Device.CodeMemorySize)
{
case 0x8000:
return (byte)(Device.Variant != 0x00 ? 0x06 : 0x05);
case 0x10000:
return (byte)(Device.Variant != 0x00 ? 0x08 : 0x07);
case 0x20000:
return (byte)(Device.Variant != 0x00 ? 0x0A : 0x09);
case 0x40000:
return (byte)(Device.Variant != 0x00 ? 0x0C : 0x0B);
case 0x80000:
return 0x0D;
}
break;
case 0x11:
if (Opts5Hibyte == 0x01)
{
return (byte)((Device.Variant & 0x80) != 0x00 ? 0x4B : 0x4C);
}
else
{
return (byte)((Device.Variant >> 0x07) | 0x0E);
}
case 0x12:
Dictionary<uint, byte> map;
if ((byte)Device.PackageDetails == 0x02)
{
map = new() { { 0x200000, 0x55 }, { 0x100000, 0x54 }, { 0x80000, 0x53 } };
if (map.TryGetValue(Device.CodeMemorySize, out byte ret))
{
return ret;
}
else
{
return (byte)(Device.CodeMemorySize == 0x40000 ? 0x52 : 0x51);
}
}
else if (Opts5Hibyte == 0xFF || Opts5Hibyte == 0x01)
{
if (Device.CodeMemorySize == 0x800000)
{
return 0x4E;
}
else
{
map = new() { { 0x400000, 0x61 }, { 0x200000, 0x60 }, { 0x100000, 0x5F }, { 0x80000, 0x5E } };
if (map.TryGetValue(Device.CodeMemorySize, out byte ret))
{
return ret;
}
else
{
return (byte)(Device.CodeMemorySize != 0x40000 ? 0x5C : 0x5D);
}
}
}
else
{
if (Opts5Hibyte == 0x00)
{
if (Device.CodeMemorySize == 0x800000)
{
return 0x4E;
}
else
{
map = new() { { 0x400000, 0x57 }, { 0x200000, 0x58 }, { 0x100000, 0x59 }, { 0x80000, 0x5A } };
if (map.TryGetValue(Device.CodeMemorySize, out byte ret))
{
return ret;
}
else
{
return (byte)(Device.CodeMemorySize == 0x40000 ? 0x5B : 0x4E);
}
}
}
}
break;
case 0x13:
byte variant = (byte)(Device.Variant & 0xF0);
map = [];
if (variant != 0x00)
{
switch (variant)
{
case 0x10:
map = new() { { 0x400000, 0x37 }, { 0x200000, 0x38 }, { 0x100000, 0x39 }, { 0x40000, 0x3B }, { 0x80000, 0x3A } };
break;
case 0x20:
return (byte)(Opts5Hibyte != 0x00 ? (Device.CodeMemorySize == 0x200000 ? 0x3C : 0x3D) :
(Device.CodeMemorySize == 0x200000 ? 0x44 : 0x45));
case 0x30:
map = new() { { 0x400000, 0x3E }, { 0x200000, 0x3F }, { 0x100000, 0x40 }, { 0x40000, 0x42 }, { 0x80000, 0x41 } };
break;
case 0x40:
map = new() { { 0x400000, 0x43 }, { 0x200000, 0x44 }, { 0x100000, 0x45 }, { 0x40000, 0x46 }, { 0x80000, 0x46 } };
break;
case 0x60:
map = new() { { 0x400000, 0x47 }, { 0x200000, 0x48 }, { 0x100000, 0x49 } };
break;
}
return (byte)(map.TryGetValue(Device.CodeMemorySize, out byte ret) ? ret : 0x00);
}
else
{
return (byte)(Device.CodeMemorySize != 0x200000 ? 0x36 : 0x35);
}
case 0x14:
return 0x4D;
case 0x15:
return 0x62;
case 0x1F:
case 0x20:
return 0x21;
case 0x1D:
if ((byte)Device.PackageDetails == 0x07)
{
return 0x28;
}
else if ((Device.PackageDetails & 0xFF000000) == 0xFC000000)
{
return 0x29;
}
else if ((Device.Variant & 0xE0) != 0x00)
{
Dictionary<byte, byte> vlut = new() { { 0x20, 0x24 }, { 0x40, 0x25 }, { 0x60, 0x26 } };
if (vlut.ContainsKey((byte)(Device.Variant & 0xE0)))
{
return vlut[(byte)(Device.Variant & 0xE0)];
}
else
{
return (byte)((Device.Variant & 0xE0) == 0x80 ? 0x27 : 0x22);
}
}
else
{
return 0x20;
}
case 0x1E:
return (byte)((Device.Variant & 2 | 0x44) >> 1);
case 0x21:
case 0x22:
case 0x23:
case 0x24:
case 0x25:
case 0x26:
return 0x20;
case 0x18:
case 0x1A:
case 0x1B:
if ((Device.Variant & 0x0F) == 0x07)
{
return 0x2C;
}
else
{
switch (Device.Variant & 0x0F)
{
case 0x07:
return 0x2C;
case 0x06:
return 0x2D;
case 0x05:
return 0x2E;
case 0x04:
return 0x2F;
case 0x03:
return 0x30;
case 0x01:
return 0x2A;
case 0x02:
return 0x2B;
default:
return 0x00;
}
}
case 0x19:
switch (Device.Variant & 0x0F)
{
case 0x01:
return 0x2A;
case 0x02:
return 0x2B;
case 0x03:
return 0x2F;
case 0x04:
return 0x2C;
default:
return 0x00;
}
case 0x1C:
return (byte)((Device.Variant & 0xF) == 0x00 ? 0x31 : 0x32);
case 0x2A:
return 0x33;
case 0x2B:
case 0x2C:
return 0x34;
case 0x2D:
return (byte)(Device.PackageDetails == 0x08 ? 0x6F : 0x70);
case 0x30:
return 0x72;
}
return Opts8Lobyte;
}
}
}