dep/rcheevos: Update to 08999e0

This commit is contained in:
Stenzek 2025-01-25 15:17:11 +10:00
parent 21aa6ead5f
commit 1bfc4b6e6c
No known key found for this signature in database
8 changed files with 632 additions and 2 deletions

View File

@ -225,6 +225,42 @@ RC_EXPORT int RC_CCONV rc_api_init_fetch_game_titles_request(rc_api_request_t* r
RC_EXPORT int RC_CCONV rc_api_process_fetch_game_titles_server_response(rc_api_fetch_game_titles_response_t* response, const rc_api_server_response_t* server_response);
RC_EXPORT void RC_CCONV rc_api_destroy_fetch_game_titles_response(rc_api_fetch_game_titles_response_t* response);
/* --- Fetch Game Hashes --- */
/**
* API parameters for a fetch games list request.
*/
typedef struct rc_api_fetch_hash_library_request_t {
/* The unique identifier of the console to query */
uint32_t console_id;
} rc_api_fetch_hash_library_request_t;
/* A hash library entry */
typedef struct rc_api_hash_library_entry_t {
/* The hash for the game */
const char* hash;
/* The unique identifier of the game */
uint32_t game_id;
} rc_api_hash_library_entry_t;
/**
* Response data for a fetch hash library request.
*/
typedef struct rc_api_fetch_hash_library_response_t {
/* An array of entries, one per game */
rc_api_hash_library_entry_t* entries;
/* The number of items in the entries array */
uint32_t num_entries;
/* Common server-provided response information */
rc_api_response_t response;
}
rc_api_fetch_hash_library_response_t;
RC_EXPORT int RC_CCONV rc_api_init_fetch_hash_library_request(rc_api_request_t* request, const rc_api_fetch_hash_library_request_t* api_params);
RC_EXPORT int RC_CCONV rc_api_process_fetch_hash_library_server_response(rc_api_fetch_hash_library_response_t* response, const rc_api_server_response_t* server_response);
RC_EXPORT void RC_CCONV rc_api_destroy_fetch_hash_library_response(rc_api_fetch_hash_library_response_t* response);
RC_END_C_DECLS
#endif /* RC_API_INFO_H */

View File

@ -147,6 +147,49 @@ RC_EXPORT int RC_CCONV rc_api_process_fetch_user_unlocks_response(rc_api_fetch_u
RC_EXPORT int RC_CCONV rc_api_process_fetch_user_unlocks_server_response(rc_api_fetch_user_unlocks_response_t* response, const rc_api_server_response_t* server_response);
RC_EXPORT void RC_CCONV rc_api_destroy_fetch_user_unlocks_response(rc_api_fetch_user_unlocks_response_t* response);
/* --- Fetch All Progress --- */
/**
* API parameters for a fetch all progress request.
*/
typedef struct rc_api_fetch_all_progress_request_t {
/* The username of the player */
const char* username;
/* The API token from the login request */
const char* api_token;
/* The unique identifier of the console to query */
uint32_t console_id;
} rc_api_fetch_all_progress_request_t;
/* An all-progress entry */
typedef struct rc_api_all_progress_entry_t {
/* The unique identifier of the game */
uint32_t game_id;
/* The total number of achievements for this game */
uint32_t num_achievements;
/* The total number of unlocked achievements for this game in softcore mode */
uint32_t num_unlocked_achievements;
/* The total number of unlocked achievements for this game in hardcore mode */
uint32_t num_unlocked_achievements_hardcore;
} rc_api_all_progress_entry_t;
/**
* Response data for a fetch all progress request.
*/
typedef struct rc_api_fetch_all_progress_response_t {
/* An array of entries, one per game */
rc_api_all_progress_entry_t* entries;
/* The number of items in the entries array */
uint32_t num_entries;
/* Common server-provided response information */
rc_api_response_t response;
} rc_api_fetch_all_progress_response_t;
RC_EXPORT int RC_CCONV rc_api_init_fetch_all_progress_request(rc_api_request_t* request, const rc_api_fetch_all_progress_request_t* api_params);
RC_EXPORT int RC_CCONV rc_api_process_fetch_all_progress_server_response(rc_api_fetch_all_progress_response_t* response, const rc_api_server_response_t* server_response);
RC_EXPORT void RC_CCONV rc_api_destroy_fetch_all_progress_response(rc_api_fetch_all_progress_response_t* response);
RC_END_C_DECLS
#endif /* RC_API_H */

View File

@ -310,6 +310,88 @@ typedef struct rc_client_subset_t {
RC_EXPORT const rc_client_subset_t* RC_CCONV rc_client_get_subset_info(rc_client_t* client, uint32_t subset_id);
/*****************************************************************************\
| Game Info |
\*****************************************************************************/
typedef struct rc_client_hash_library_entry_t
{
/* The hash for the game */
const char* hash;
/* The unique identifier of the game */
uint32_t game_id;
} rc_client_hash_library_entry_t;
typedef struct rc_client_hash_library_t
{
/* An array of entries, one per game */
rc_client_hash_library_entry_t* entries;
/* The number of items in the entries array */
uint32_t num_entries;
} rc_client_hash_library_t;
/**
* Callback that is fired when a hash library request completes. list may be null if the query failed.
*/
typedef void(RC_CCONV* rc_client_fetch_hash_library_callback_t)(int result, const char* error_message,
rc_client_hash_library_t* list, rc_client_t* client,
void* callback_userdata);
/**
* Starts an asynchronous request for all hashes for the given console.
* This request returns a mapping from hashes to the game's unique identifier. A single game may have multiple
* hashes in the case of multi-disc games, or variants that are still compatible with the same achievement set.
*/
RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_fetch_hash_library(
rc_client_t* client, uint32_t console_id, rc_client_fetch_hash_library_callback_t callback, void* callback_userdata);
/**
* Destroys a previously-allocated result from the rc_client_destroy_hash_library() callback.
*/
RC_EXPORT void RC_CCONV rc_client_destroy_hash_library(rc_client_hash_library_t* list);
typedef struct rc_client_all_progress_list_entry_t
{
/* The unique identifier of the game */
uint32_t game_id;
/* The total number of achievements for this game */
uint32_t num_achievements;
/* The total number of unlocked achievements for this game in softcore mode */
uint32_t num_unlocked_achievements;
/* The total number of unlocked achievements for this game in hardcore mode */
uint32_t num_unlocked_achievements_hardcore;
} rc_client_all_progress_list_entry_t;
typedef struct rc_client_all_progress_list_t
{
/* An array of entries, one per game */
rc_client_all_progress_list_entry_t* entries;
/* The number of items in the entries array */
uint32_t num_entries;
} rc_client_all_progress_list_t;
/**
* Callback that is fired when an all progress query completes. list may be null if the query failed.
*/
typedef void(RC_CCONV* rc_client_fetch_all_progress_list_callback_t)(int result, const char* error_message,
rc_client_all_progress_list_t* list,
rc_client_t* client, void* callback_userdata);
/**
* Starts an asynchronous request for all progress for the given console.
* This query returns the total number of achievements for all games tracked by this console, as well as
* the user's achievement unlock count for both softcore and hardcore modes.
*/
RC_EXPORT rc_client_async_handle_t* RC_CCONV
rc_client_begin_fetch_all_progress_list(rc_client_t* client, uint32_t console_id,
rc_client_fetch_all_progress_list_callback_t callback, void* callback_userdata);
/**
* Destroys a previously-allocated result from the rc_client_begin_fetch_all_progress_list() callback.
*/
RC_EXPORT void RC_CCONV rc_client_destroy_all_progress_list(rc_client_all_progress_list_t* list);
/*****************************************************************************\
| Achievements |
\*****************************************************************************/

View File

@ -1,6 +1,7 @@
#include "rc_api_info.h"
#include "rc_api_common.h"
#include "rc_consoles.h"
#include "rc_runtime_types.h"
#include "../rc_compat.h"
@ -464,3 +465,87 @@ int rc_api_process_fetch_game_titles_server_response(rc_api_fetch_game_titles_re
void rc_api_destroy_fetch_game_titles_response(rc_api_fetch_game_titles_response_t* response) {
rc_buffer_destroy(&response->response.buffer);
}
/* --- Fetch Game Hashes --- */
int rc_api_init_fetch_hash_library_request(rc_api_request_t* request,
const rc_api_fetch_hash_library_request_t* api_params)
{
rc_api_url_builder_t builder;
rc_api_url_build_dorequest_url(request);
if (api_params->console_id == RC_CONSOLE_UNKNOWN)
return RC_INVALID_STATE;
rc_url_builder_init(&builder, &request->buffer, 48);
rc_url_builder_append_str_param(&builder, "r", "hashlibrary");
rc_url_builder_append_unum_param(&builder, "c", api_params->console_id);
request->post_data = rc_url_builder_finalize(&builder);
request->content_type = RC_CONTENT_TYPE_URLENCODED;
return builder.result;
}
int rc_api_process_fetch_hash_library_server_response(rc_api_fetch_hash_library_response_t* response,
const rc_api_server_response_t* server_response)
{
rc_api_hash_library_entry_t* entry;
rc_json_iterator_t iterator;
rc_json_field_t field;
int result;
char* end;
rc_json_field_t fields[] = {
RC_JSON_NEW_FIELD("Success"),
RC_JSON_NEW_FIELD("Error"),
RC_JSON_NEW_FIELD("MD5List"),
};
memset(response, 0, sizeof(*response));
rc_buffer_init(&response->response.buffer);
result =
rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0]));
if (result != RC_OK)
return result;
if (!fields[2].value_start)
{
/* call rc_json_get_required_object to generate the error message */
rc_json_get_required_object(NULL, 0, &response->response, &fields[2], "MD5List");
return RC_MISSING_VALUE;
}
response->num_entries = fields[2].array_size;
rc_buffer_reserve(&response->response.buffer, response->num_entries * (32 + sizeof(rc_api_hash_library_entry_t)));
response->entries = (rc_api_hash_library_entry_t*)rc_buffer_alloc(
&response->response.buffer, response->num_entries * sizeof(rc_api_hash_library_entry_t));
if (!response->entries)
return RC_OUT_OF_MEMORY;
memset(&iterator, 0, sizeof(iterator));
iterator.json = fields[2].value_start;
iterator.end = fields[2].value_end;
entry = response->entries;
while (rc_json_get_next_object_field(&iterator, &field))
{
/* TODO: This isn't handling escape characters in the key, the RC JSON parsing functions have no method for it. */
entry->hash = rc_buffer_strncpy(&response->response.buffer, field.name, field.name_len);
field.name = "";
if (!rc_json_get_unum(&entry->game_id, &field, ""))
return RC_MISSING_VALUE;
++entry;
}
return RC_OK;
}
void rc_api_destroy_fetch_hash_library_response(rc_api_fetch_hash_library_response_t* response)
{
rc_buffer_destroy(&response->response.buffer);
}

View File

@ -1,8 +1,10 @@
#include "rc_api_user.h"
#include "rc_api_common.h"
#include "rc_consoles.h"
#include "../rc_version.h"
#include <stdlib.h>
#include <string.h>
/* --- Login --- */
@ -252,3 +254,101 @@ int rc_api_process_fetch_user_unlocks_server_response(rc_api_fetch_user_unlocks_
void rc_api_destroy_fetch_user_unlocks_response(rc_api_fetch_user_unlocks_response_t* response) {
rc_buffer_destroy(&response->response.buffer);
}
/* --- Fetch All Progress --- */
int rc_api_init_fetch_all_progress_request(rc_api_request_t* request,
const rc_api_fetch_all_progress_request_t* api_params)
{
rc_api_url_builder_t builder;
rc_api_url_build_dorequest_url(request);
if (api_params->console_id == RC_CONSOLE_UNKNOWN)
return RC_INVALID_STATE;
rc_url_builder_init(&builder, &request->buffer, 48);
if (rc_api_url_build_dorequest(&builder, "allprogress", api_params->username, api_params->api_token))
{
rc_url_builder_append_unum_param(&builder, "c", api_params->console_id);
request->post_data = rc_url_builder_finalize(&builder);
request->content_type = RC_CONTENT_TYPE_URLENCODED;
}
return builder.result;
}
int rc_api_process_fetch_all_progress_server_response(rc_api_fetch_all_progress_response_t* response,
const rc_api_server_response_t* server_response)
{
rc_api_all_progress_entry_t* entry;
rc_json_iterator_t iterator;
rc_json_field_t field;
int result;
char* end;
rc_json_field_t fields[] = {
RC_JSON_NEW_FIELD("Success"),
RC_JSON_NEW_FIELD("Error"),
RC_JSON_NEW_FIELD("Response"),
};
rc_json_field_t entry_fields[] = {
RC_JSON_NEW_FIELD("Achievements"),
RC_JSON_NEW_FIELD("Unlocked"),
RC_JSON_NEW_FIELD("UnlockedHardcore"),
};
memset(response, 0, sizeof(*response));
rc_buffer_init(&response->response.buffer);
result =
rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0]));
if (result != RC_OK)
return result;
if (!fields[2].value_start)
{
/* call rc_json_get_required_object to generate the error message */
rc_json_get_required_object(NULL, 0, &response->response, &fields[2], "Response");
return RC_MISSING_VALUE;
}
response->num_entries = fields[2].array_size;
rc_buffer_reserve(&response->response.buffer, response->num_entries * sizeof(rc_api_all_progress_entry_t));
response->entries = (rc_api_all_progress_entry_t*)rc_buffer_alloc(
&response->response.buffer, response->num_entries * sizeof(rc_api_all_progress_entry_t));
if (!response->entries)
return RC_OUT_OF_MEMORY;
memset(&iterator, 0, sizeof(iterator));
iterator.json = fields[2].value_start;
iterator.end = fields[2].value_end;
entry = response->entries;
while (rc_json_get_next_object_field(&iterator, &field))
{
entry->game_id = strtol(field.name, &end, 10);
field.name = "";
if (!rc_json_get_required_object(entry_fields, sizeof(entry_fields) / sizeof(entry_fields[0]), response, &field,
""))
{
return RC_MISSING_VALUE;
}
rc_json_get_optional_unum(&entry->num_achievements, &entry_fields[0], "Achievements", 0);
rc_json_get_optional_unum(&entry->num_unlocked_achievements, &entry_fields[1], "Unlocked", 0);
rc_json_get_optional_unum(&entry->num_unlocked_achievements_hardcore, &entry_fields[2], "UnlockedHardcore", 0);
++entry;
}
return RC_OK;
}
void rc_api_destroy_fetch_all_progress_response(rc_api_fetch_all_progress_response_t* response)
{
rc_buffer_destroy(&response->response.buffer);
}

View File

@ -3209,6 +3209,272 @@ const rc_client_subset_t* rc_client_get_subset_info(rc_client_t* client, uint32_
return NULL;
}
/* ===== Game Info ===== */
typedef struct rc_client_fetch_hash_library_callback_data_t
{
rc_client_t* client;
rc_client_fetch_hash_library_callback_t callback;
void* callback_userdata;
uint32_t console_id;
rc_client_async_handle_t async_handle;
} rc_client_fetch_hash_library_callback_data_t;
static void rc_client_fetch_hash_library_callback(const rc_api_server_response_t* server_response, void* callback_data)
{
rc_client_fetch_hash_library_callback_data_t* hashlib_callback_data =
(rc_client_fetch_hash_library_callback_data_t*)callback_data;
rc_client_t* client = hashlib_callback_data->client;
rc_api_fetch_hash_library_response_t hashlib_response;
const char* error_message;
int result;
result = rc_client_end_async(client, &hashlib_callback_data->async_handle);
if (result)
{
if (result != RC_CLIENT_ASYNC_DESTROYED)
RC_CLIENT_LOG_VERBOSE(client, "Fetch hash library aborted");
free(hashlib_callback_data);
return;
}
result = rc_api_process_fetch_hash_library_server_response(&hashlib_response, server_response);
error_message =
rc_client_server_error_message(&result, server_response->http_status_code, &hashlib_response.response);
if (error_message)
{
RC_CLIENT_LOG_ERR_FORMATTED(client, "Fetch hash library for console %u failed: %s",
hashlib_callback_data->console_id, error_message);
hashlib_callback_data->callback(result, error_message, NULL, client, hashlib_callback_data->callback_userdata);
}
else
{
rc_client_hash_library_t* list;
const size_t list_size = sizeof(*list) + sizeof(rc_client_leaderboard_entry_t) * hashlib_response.num_entries;
size_t needed_size = list_size;
uint32_t i;
for (i = 0; i < hashlib_response.num_entries; i++)
needed_size += strlen(hashlib_response.entries[i].hash) + 1;
list = (rc_client_hash_library_t*)malloc(needed_size);
if (!list)
{
hashlib_callback_data->callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client,
hashlib_callback_data->callback_userdata);
}
else
{
rc_client_hash_library_entry_t* entry = list->entries =
(rc_client_hash_library_entry_t*)((uint8_t*)list + sizeof(*list));
char* hash = (char*)((uint8_t*)list + list_size);
const rc_api_hash_library_entry_t* hlentry = hashlib_response.entries;
const rc_api_hash_library_entry_t* stop = hlentry + hashlib_response.num_entries;
for (; hlentry < stop; ++hlentry, ++entry)
{
const size_t len = strlen(hlentry->hash) + 1;
entry->hash = hash;
entry->game_id = hlentry->game_id;
memcpy(hash, hlentry->hash, len);
hash += len;
}
list->num_entries = hashlib_response.num_entries;
hashlib_callback_data->callback(RC_OK, NULL, list, client, hashlib_callback_data->callback_userdata);
}
}
rc_api_destroy_fetch_hash_library_response(&hashlib_response);
free(hashlib_callback_data);
}
rc_client_async_handle_t* rc_client_begin_fetch_hash_library(rc_client_t* client, uint32_t console_id,
rc_client_fetch_hash_library_callback_t callback,
void* callback_userdata)
{
rc_api_fetch_hash_library_request_t api_params;
rc_client_fetch_hash_library_callback_data_t* callback_data;
rc_client_async_handle_t* async_handle;
rc_api_request_t request;
int result;
const char* error_message;
if (!client)
{
callback(RC_INVALID_STATE, "client is required", NULL, client, callback_userdata);
return NULL;
}
api_params.console_id = console_id;
result = rc_api_init_fetch_hash_library_request(&request, &api_params);
if (result != RC_OK)
{
error_message = rc_error_str(result);
callback(result, error_message, NULL, client, callback_userdata);
return NULL;
}
callback_data = (rc_client_fetch_hash_library_callback_data_t*)calloc(1, sizeof(*callback_data));
if (!callback_data)
{
callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, callback_userdata);
return NULL;
}
callback_data->client = client;
callback_data->callback = callback;
callback_data->callback_userdata = callback_userdata;
callback_data->console_id = console_id;
async_handle = &callback_data->async_handle;
rc_client_begin_async(client, async_handle);
client->callbacks.server_call(&request, rc_client_fetch_hash_library_callback, callback_data, client);
rc_api_destroy_request(&request);
return rc_client_async_handle_valid(client, async_handle) ? async_handle : NULL;
}
void rc_client_destroy_hash_library(rc_client_hash_library_t* list)
{
free(list);
}
typedef struct rc_client_fetch_all_progress_callback_data_t
{
rc_client_t* client;
rc_client_fetch_all_progress_list_callback_t callback;
void* callback_userdata;
uint32_t console_id;
rc_client_async_handle_t async_handle;
} rc_client_fetch_all_progress_callback_data_t;
static void rc_client_fetch_all_progress_callback(const rc_api_server_response_t* server_response, void* callback_data)
{
rc_client_fetch_all_progress_callback_data_t* ap_callback_data =
(rc_client_fetch_all_progress_callback_data_t*)callback_data;
rc_client_t* client = ap_callback_data->client;
rc_api_fetch_all_progress_response_t ap_response;
const char* error_message;
int result;
result = rc_client_end_async(client, &ap_callback_data->async_handle);
if (result)
{
if (result != RC_CLIENT_ASYNC_DESTROYED)
RC_CLIENT_LOG_VERBOSE(client, "Fetch all progress aborted");
free(ap_callback_data);
return;
}
result = rc_api_process_fetch_all_progress_server_response(&ap_response, server_response);
error_message = rc_client_server_error_message(&result, server_response->http_status_code, &ap_response.response);
if (error_message)
{
RC_CLIENT_LOG_ERR_FORMATTED(client, "Fetch all progress for console %u failed: %s", ap_callback_data->console_id,
error_message);
ap_callback_data->callback(result, error_message, NULL, client, ap_callback_data->callback_userdata);
}
else
{
rc_client_all_progress_list_t* list;
const size_t list_size = sizeof(*list) + sizeof(rc_client_all_progress_list_entry_t) * ap_response.num_entries;
list = (rc_client_all_progress_list_t*)malloc(list_size);
if (!list)
{
ap_callback_data->callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client,
ap_callback_data->callback_userdata);
}
else
{
rc_client_all_progress_list_entry_t* entry = list->entries =
(rc_client_all_progress_list_entry_t*)((uint8_t*)list + sizeof(*list));
const rc_api_all_progress_entry_t* hlentry = ap_response.entries;
const rc_api_all_progress_entry_t* stop = hlentry + ap_response.num_entries;
for (; hlentry < stop; ++hlentry, ++entry)
{
entry->game_id = hlentry->game_id;
entry->num_achievements = hlentry->num_achievements;
entry->num_unlocked_achievements = hlentry->num_unlocked_achievements;
entry->num_unlocked_achievements_hardcore = hlentry->num_unlocked_achievements_hardcore;
}
list->num_entries = ap_response.num_entries;
ap_callback_data->callback(RC_OK, NULL, list, client, ap_callback_data->callback_userdata);
}
}
rc_api_destroy_fetch_all_progress_response(&ap_response);
free(ap_callback_data);
}
rc_client_async_handle_t* rc_client_begin_fetch_all_progress_list(rc_client_t* client, uint32_t console_id,
rc_client_fetch_all_progress_list_callback_t callback,
void* callback_userdata)
{
rc_api_fetch_all_progress_request_t api_params;
rc_client_fetch_all_progress_callback_data_t* callback_data;
rc_client_async_handle_t* async_handle;
rc_api_request_t request;
int result;
const char* error_message;
if (!client)
{
callback(RC_INVALID_STATE, "client is required", NULL, client, callback_userdata);
return NULL;
}
else if (client->state.user != RC_CLIENT_USER_STATE_LOGGED_IN)
{
callback(RC_INVALID_STATE, "client must be logged in", NULL, client, callback_userdata);
return NULL;
}
api_params.username = client->user.username;
api_params.api_token = client->user.token;
api_params.console_id = console_id;
result = rc_api_init_fetch_all_progress_request(&request, &api_params);
if (result != RC_OK)
{
error_message = rc_error_str(result);
callback(result, error_message, NULL, client, callback_userdata);
return NULL;
}
callback_data = (rc_client_fetch_all_progress_callback_data_t*)calloc(1, sizeof(*callback_data));
if (!callback_data)
{
callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, callback_userdata);
return NULL;
}
callback_data->client = client;
callback_data->callback = callback;
callback_data->callback_userdata = callback_userdata;
callback_data->console_id = console_id;
async_handle = &callback_data->async_handle;
rc_client_begin_async(client, async_handle);
client->callbacks.server_call(&request, rc_client_fetch_all_progress_callback, callback_data, client);
rc_api_destroy_request(&request);
return rc_client_async_handle_valid(client, async_handle) ? async_handle : NULL;
}
void rc_client_destroy_all_progress_list(rc_client_all_progress_list_t* list)
{
free(list);
}
/* ===== Achievements ===== */
static void rc_client_update_achievement_display_information(rc_client_t* client, rc_client_achievement_info_t* achievement, time_t recent_unlock_time)

View File

@ -465,6 +465,17 @@ int rc_operand_type_is_memref(uint8_t type) {
}
}
int rc_operand_type_is_transform(uint8_t type) {
switch (type) {
case RC_OPERAND_BCD:
case RC_OPERAND_INVERTED:
return 1;
default:
return 0;
}
}
int rc_operand_is_memref(const rc_operand_t* self) {
return rc_operand_type_is_memref(self->type);
}
@ -603,9 +614,15 @@ void rc_operand_addsource(rc_operand_t* self, rc_parse_state_t* parse, uint8_t n
self->value.memref = (rc_memref_t*)modified_memref;
if (!rc_operand_is_memref(self)) {
/* if adding a constant, change the type to be address (current value) */
if (!rc_operand_is_memref(self))
self->type = self->memref_access_type = RC_OPERAND_ADDRESS;
}
else if (rc_operand_type_is_transform(self->type)) {
/* transform is applied in the modified_memref. change the type to be
* address (current value) to avoid applying the transform again */
self->type = self->memref_access_type = RC_OPERAND_ADDRESS;
}
/* result of an AddSource operation is always a 32-bit integer (even if parent or modifier is a float) */
self->size = RC_MEMSIZE_32_BITS;

View File

@ -352,6 +352,7 @@ int rc_operand_is_float_memref(const rc_operand_t* self);
int rc_operand_is_float(const rc_operand_t* self);
int rc_operand_is_recall(const rc_operand_t* self);
int rc_operand_type_is_memref(uint8_t type);
int rc_operand_type_is_transform(uint8_t type);
int rc_operands_are_equal(const rc_operand_t* left, const rc_operand_t* right);
void rc_operand_addsource(rc_operand_t* self, rc_parse_state_t* parse, uint8_t new_size);
void rc_operand_set_const(rc_operand_t* self, uint32_t value);