mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-11-03 23:28:48 +00:00 
			
		
		
		
	Service::CFG: add SetConfigInfoBlk4
This commit is contained in:
		
							parent
							
								
									f00e8d4b2b
								
							
						
					
					
						commit
						324c8d21a4
					
				
					 4 changed files with 73 additions and 8 deletions
				
			
		| 
						 | 
				
			
			@ -223,6 +223,22 @@ void GetConfigInfoBlk8(Service::Interface* self) {
 | 
			
		|||
    Memory::WriteBlock(data_pointer, data.data(), data.size());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SetConfigInfoBlk4(Service::Interface* self) {
 | 
			
		||||
    u32* cmd_buff = Kernel::GetCommandBuffer();
 | 
			
		||||
    u32 block_id = cmd_buff[1];
 | 
			
		||||
    u32 size = cmd_buff[2];
 | 
			
		||||
    VAddr data_pointer = cmd_buff[4];
 | 
			
		||||
 | 
			
		||||
    if (!Memory::IsValidVirtualAddress(data_pointer)) {
 | 
			
		||||
        cmd_buff[1] = -1; // TODO(Subv): Find the right error code
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::vector<u8> data(size);
 | 
			
		||||
    Memory::ReadBlock(data_pointer, data.data(), data.size());
 | 
			
		||||
    cmd_buff[1] = Service::CFG::SetConfigInfoBlock(block_id, size, 0x4, data.data()).raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UpdateConfigNANDSavegame(Service::Interface* self) {
 | 
			
		||||
    u32* cmd_buff = Kernel::GetCommandBuffer();
 | 
			
		||||
    cmd_buff[1] = Service::CFG::UpdateConfigNANDSavegame().raw;
 | 
			
		||||
| 
						 | 
				
			
			@ -233,13 +249,13 @@ void FormatConfig(Service::Interface* self) {
 | 
			
		|||
    cmd_buff[1] = Service::CFG::FormatConfig().raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output) {
 | 
			
		||||
static ResultVal<void*> GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 flag) {
 | 
			
		||||
    // Read the header
 | 
			
		||||
    SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data());
 | 
			
		||||
 | 
			
		||||
    auto itr = std::find_if(std::begin(config->block_entries), std::end(config->block_entries),
 | 
			
		||||
        [&](const SaveConfigBlockEntry& entry) {
 | 
			
		||||
            return entry.block_id == block_id && (entry.flags & flag);
 | 
			
		||||
            return entry.block_id == block_id;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    if (itr == std::end(config->block_entries)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -247,17 +263,38 @@ ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output) {
 | 
			
		|||
        return ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((itr->flags & flag) == 0) {
 | 
			
		||||
        LOG_ERROR(Service_CFG, "Invalid flag %u for config block 0x%X with size %u", flag, block_id, size);
 | 
			
		||||
        return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (itr->size != size) {
 | 
			
		||||
        LOG_ERROR(Service_CFG, "Invalid size %u for config block 0x%X with flags %u", size, block_id, flag);
 | 
			
		||||
        return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void* pointer;
 | 
			
		||||
 | 
			
		||||
    // The data is located in the block header itself if the size is less than 4 bytes
 | 
			
		||||
    if (itr->size <= 4)
 | 
			
		||||
        memcpy(output, &itr->offset_or_data, itr->size);
 | 
			
		||||
        pointer = &itr->offset_or_data;
 | 
			
		||||
    else
 | 
			
		||||
        memcpy(output, &cfg_config_file_buffer[itr->offset_or_data], itr->size);
 | 
			
		||||
        pointer = &cfg_config_file_buffer[itr->offset_or_data];
 | 
			
		||||
 | 
			
		||||
    return MakeResult<void*>(pointer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output) {
 | 
			
		||||
    void* pointer;
 | 
			
		||||
    CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag));
 | 
			
		||||
    memcpy(output, pointer, size);
 | 
			
		||||
    return RESULT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input) {
 | 
			
		||||
    void* pointer;
 | 
			
		||||
    CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag));
 | 
			
		||||
    memcpy(pointer, input, size);
 | 
			
		||||
    return RESULT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -184,6 +184,22 @@ void GetConfigInfoBlk2(Service::Interface* self);
 | 
			
		|||
 */
 | 
			
		||||
void GetConfigInfoBlk8(Service::Interface* self);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * CFG::SetConfigInfoBlk4 service function
 | 
			
		||||
 *  Inputs:
 | 
			
		||||
 *      0 : 0x04020082 / 0x08020082
 | 
			
		||||
 *      1 : Block ID
 | 
			
		||||
 *      2 : Size
 | 
			
		||||
 *      3 : Descriptor for the output buffer
 | 
			
		||||
 *      4 : Output buffer pointer
 | 
			
		||||
 *  Outputs:
 | 
			
		||||
 *      1 : Result of function, 0 on success, otherwise error code
 | 
			
		||||
 *  Note:
 | 
			
		||||
 *      The parameters order is different from GetConfigInfoBlk2/8's,
 | 
			
		||||
 *      where Block ID and Size are switched.
 | 
			
		||||
 */
 | 
			
		||||
void SetConfigInfoBlk4(Service::Interface* self);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * CFG::UpdateConfigNANDSavegame service function
 | 
			
		||||
 *  Inputs:
 | 
			
		||||
| 
						 | 
				
			
			@ -212,7 +228,19 @@ void FormatConfig(Service::Interface* self);
 | 
			
		|||
 * @param output A pointer where we will write the read data
 | 
			
		||||
 * @returns ResultCode indicating the result of the operation, 0 on success
 | 
			
		||||
 */
 | 
			
		||||
ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output);
 | 
			
		||||
ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reads data from input and writes to a block with the specified id and flag
 | 
			
		||||
 * in the Config savegame buffer.
 | 
			
		||||
 * The input size must match exactly the size of the target block
 | 
			
		||||
 * @param block_id The id of the block we want to write
 | 
			
		||||
 * @param size The size of the block we want to write
 | 
			
		||||
 * @param flag The target block must have this flag set
 | 
			
		||||
 * @param input A pointer where we will read data and write to Config savegame buffer
 | 
			
		||||
 * @returns ResultCode indicating the result of the operation, 0 on success
 | 
			
		||||
 */
 | 
			
		||||
ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Creates a block with the specified id and writes the input data to the cfg savegame buffer in memory.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 | 
			
		|||
    {0x000A0040, GetCountryCodeID,                     "GetCountryCodeID"},
 | 
			
		||||
    // cfg:i
 | 
			
		||||
    {0x04010082, GetConfigInfoBlk8,                    "GetConfigInfoBlk8"},
 | 
			
		||||
    {0x04020082, nullptr,                              "SetConfigInfoBlk4"},
 | 
			
		||||
    {0x04020082, SetConfigInfoBlk4,                    "SetConfigInfoBlk4"},
 | 
			
		||||
    {0x04030000, UpdateConfigNANDSavegame,             "UpdateConfigNANDSavegame"},
 | 
			
		||||
    {0x04040042, nullptr,                              "GetLocalFriendCodeSeedData"},
 | 
			
		||||
    {0x04050000, nullptr,                              "GetLocalFriendCodeSeed"},
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 | 
			
		|||
    {0x04080042, nullptr,                              "SecureInfoGetSerialNo"},
 | 
			
		||||
    {0x04090000, nullptr,                              "UpdateConfigBlk00040003"},
 | 
			
		||||
    {0x08010082, GetConfigInfoBlk8,                    "GetConfigInfoBlk8"},
 | 
			
		||||
    {0x08020082, nullptr,                              "SetConfigInfoBlk4"},
 | 
			
		||||
    {0x08020082, SetConfigInfoBlk4,                    "SetConfigInfoBlk4"},
 | 
			
		||||
    {0x08030000, UpdateConfigNANDSavegame,             "UpdateConfigNANDSavegame"},
 | 
			
		||||
    {0x080400C2, nullptr,                              "CreateConfigInfoBlk"},
 | 
			
		||||
    {0x08050000, nullptr,                              "DeleteConfigNANDSavefile"},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 | 
			
		|||
    {0x000A0040, GetCountryCodeID,                     "GetCountryCodeID"},
 | 
			
		||||
    // cfg:s
 | 
			
		||||
    {0x04010082, GetConfigInfoBlk8,                    "GetConfigInfoBlk8"},
 | 
			
		||||
    {0x04020082, nullptr,                              "SetConfigInfoBlk4"},
 | 
			
		||||
    {0x04020082, SetConfigInfoBlk4,                    "SetConfigInfoBlk4"},
 | 
			
		||||
    {0x04030000, UpdateConfigNANDSavegame,             "UpdateConfigNANDSavegame"},
 | 
			
		||||
    {0x04040042, nullptr,                              "GetLocalFriendCodeSeedData"},
 | 
			
		||||
    {0x04050000, nullptr,                              "GetLocalFriendCodeSeed"},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue