forked from dolphin-emu/dolphin
		
	
		
			
				
	
	
		
			195 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright 2009 Dolphin Emulator Project
 | 
						|
// Licensed under GPLv2+
 | 
						|
// Refer to the license.txt file included.
 | 
						|
 | 
						|
#pragma once
 | 
						|
 | 
						|
#include <algorithm>
 | 
						|
#include <cstdio>
 | 
						|
#include <cstring>
 | 
						|
#include <string>
 | 
						|
#include <vector>
 | 
						|
 | 
						|
#include "Common/CommonTypes.h"
 | 
						|
#include "Common/Logging/Log.h"
 | 
						|
#include "Common/MsgHandler.h"
 | 
						|
#include "Common/NandPaths.h"
 | 
						|
 | 
						|
namespace File
 | 
						|
{
 | 
						|
class IOFile;
 | 
						|
}
 | 
						|
 | 
						|
// This class is meant to edit the values in a given Wii SYSCONF file
 | 
						|
// It currently does not add/remove/rearrange sections,
 | 
						|
// instead only modifies exiting sections' data
 | 
						|
 | 
						|
#define SYSCONF_SIZE 0x4000
 | 
						|
 | 
						|
enum SysconfType
 | 
						|
{
 | 
						|
  Type_BigArray = 1,
 | 
						|
  Type_SmallArray,
 | 
						|
  Type_Byte,
 | 
						|
  Type_Short,
 | 
						|
  Type_Long,
 | 
						|
  Type_LongLong,
 | 
						|
  Type_Bool
 | 
						|
};
 | 
						|
 | 
						|
struct SSysConfHeader
 | 
						|
{
 | 
						|
  char version[4];
 | 
						|
  u16 numEntries;
 | 
						|
};
 | 
						|
 | 
						|
struct SSysConfEntry
 | 
						|
{
 | 
						|
  u16 offset = 0;
 | 
						|
  SysconfType type;
 | 
						|
  u8 nameLength = 0;
 | 
						|
  char name[32] = {};
 | 
						|
  u16 dataLength = 0;
 | 
						|
  std::vector<u8> data;
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  T GetData() const
 | 
						|
  {
 | 
						|
    T extracted_data;
 | 
						|
    std::memcpy(&extracted_data, data.data(), sizeof(T));
 | 
						|
    return extracted_data;
 | 
						|
  }
 | 
						|
  bool GetArrayData(u8* dest, u16 destSize) const
 | 
						|
  {
 | 
						|
    if (dest && destSize >= dataLength)
 | 
						|
    {
 | 
						|
      memcpy(dest, data.data(), dataLength);
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  bool SetArrayData(const u8* buffer, u16 bufferSize)
 | 
						|
  {
 | 
						|
    if (buffer)
 | 
						|
    {
 | 
						|
      memcpy(data.data(), buffer, std::min<u16>(bufferSize, dataLength));
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class SysConf
 | 
						|
{
 | 
						|
public:
 | 
						|
  SysConf(Common::FromWhichRoot root_type);
 | 
						|
  ~SysConf();
 | 
						|
 | 
						|
  bool IsValid() const { return m_IsValid; }
 | 
						|
  template <class T>
 | 
						|
  T GetData(const char* sectionName) const
 | 
						|
  {
 | 
						|
    if (!m_IsValid)
 | 
						|
    {
 | 
						|
      PanicAlertT("Trying to read from invalid SYSCONF");
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    auto index = m_Entries.cbegin();
 | 
						|
    for (; index < m_Entries.cend() - 1; ++index)
 | 
						|
    {
 | 
						|
      if (strcmp(index->name, sectionName) == 0)
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    if (index == m_Entries.cend() - 1)
 | 
						|
    {
 | 
						|
      PanicAlertT("Section %s not found in SYSCONF", sectionName);
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    return index->GetData<T>();
 | 
						|
  }
 | 
						|
 | 
						|
  bool GetArrayData(const char* sectionName, u8* dest, u16 destSize) const
 | 
						|
  {
 | 
						|
    if (!m_IsValid)
 | 
						|
    {
 | 
						|
      PanicAlertT("Trying to read from invalid SYSCONF");
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    auto index = m_Entries.cbegin();
 | 
						|
    for (; index < m_Entries.cend() - 1; ++index)
 | 
						|
    {
 | 
						|
      if (strcmp(index->name, sectionName) == 0)
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    if (index == m_Entries.cend() - 1)
 | 
						|
    {
 | 
						|
      PanicAlertT("Section %s not found in SYSCONF", sectionName);
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    return index->GetArrayData(dest, destSize);
 | 
						|
  }
 | 
						|
 | 
						|
  bool SetArrayData(const char* sectionName, const u8* buffer, u16 bufferSize)
 | 
						|
  {
 | 
						|
    if (!m_IsValid)
 | 
						|
      return false;
 | 
						|
 | 
						|
    auto index = m_Entries.begin();
 | 
						|
    for (; index < m_Entries.end() - 1; ++index)
 | 
						|
    {
 | 
						|
      if (strcmp(index->name, sectionName) == 0)
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    if (index == m_Entries.end() - 1)
 | 
						|
    {
 | 
						|
      PanicAlertT("Section %s not found in SYSCONF", sectionName);
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    return index->SetArrayData(buffer, bufferSize);
 | 
						|
  }
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  bool SetData(const char* sectionName, T newValue)
 | 
						|
  {
 | 
						|
    if (!m_IsValid)
 | 
						|
      return false;
 | 
						|
 | 
						|
    auto index = m_Entries.begin();
 | 
						|
    for (; index < m_Entries.end() - 1; ++index)
 | 
						|
    {
 | 
						|
      if (strcmp(index->name, sectionName) == 0)
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    if (index == m_Entries.end() - 1)
 | 
						|
    {
 | 
						|
      PanicAlertT("Section %s not found in SYSCONF", sectionName);
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    std::memcpy(index->data.data(), &newValue, sizeof(T));
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  bool Save();
 | 
						|
  bool SaveToFile(const std::string& filename);
 | 
						|
  bool LoadFromFile(const std::string& filename);
 | 
						|
  bool Reload();
 | 
						|
  void UpdateLocation(Common::FromWhichRoot root_type);
 | 
						|
 | 
						|
private:
 | 
						|
  bool LoadFromFileInternal(File::IOFile&& file);
 | 
						|
  void GenerateSysConf();
 | 
						|
  void Clear();
 | 
						|
  void ApplySettingsFromMovie();
 | 
						|
 | 
						|
  std::string m_Filename;
 | 
						|
  std::string m_FilenameDefault;
 | 
						|
  std::vector<SSysConfEntry> m_Entries;
 | 
						|
  bool m_IsValid = false;
 | 
						|
};
 |