dep/rcheevos: Update to 8a717b1

This commit is contained in:
Stenzek
2023-11-06 19:41:10 +10:00
parent a4127aa2ea
commit f62a3ffbfa
50 changed files with 1584 additions and 1310 deletions

View File

@ -2,7 +2,7 @@
#include "rc_api_request.h"
#include "rc_api_runtime.h"
#include "../rcheevos/rc_compat.h"
#include "../rc_compat.h"
#include <ctype.h>
#include <stdio.h>
@ -16,11 +16,9 @@
static char* g_host = NULL;
static char* g_imagehost = NULL;
#undef DEBUG_BUFFERS
/* --- rc_json --- */
static int rc_json_parse_object(rc_json_iterator_t* iterator, rc_json_field_t* fields, size_t field_count, unsigned* fields_seen);
static int rc_json_parse_object(rc_json_iterator_t* iterator, rc_json_field_t* fields, size_t field_count, uint32_t* fields_seen);
static int rc_json_parse_array(rc_json_iterator_t* iterator, rc_json_field_t* field);
static int rc_json_match_char(rc_json_iterator_t* iterator, char c)
@ -184,9 +182,9 @@ static int rc_json_get_next_field(rc_json_iterator_t* iterator, rc_json_field_t*
return RC_OK;
}
static int rc_json_parse_object(rc_json_iterator_t* iterator, rc_json_field_t* fields, size_t field_count, unsigned* fields_seen) {
static int rc_json_parse_object(rc_json_iterator_t* iterator, rc_json_field_t* fields, size_t field_count, uint32_t* fields_seen) {
size_t i;
unsigned num_fields = 0;
uint32_t num_fields = 0;
rc_json_field_t field;
int result;
@ -261,12 +259,7 @@ static int rc_json_extract_html_error(rc_api_response_t* response, const rc_api_
if (isdigit((int)*title_start)) {
const char* title_end = strstr(title_start + 7, "</title>");
if (title_end) {
char* dst = rc_buf_reserve(&response->buffer, (title_end - title_start) + 1);
response->error_message = dst;
memcpy(dst, title_start, title_end - title_start);
dst += (title_end - title_start);
*dst++ = '\0';
rc_buf_consume(&response->buffer, response->error_message, dst);
response->error_message = rc_buffer_strncpy(&response->buffer, title_start, title_end - title_start);
response->succeeded = 0;
return RC_INVALID_JSON;
}
@ -279,19 +272,38 @@ static int rc_json_extract_html_error(rc_api_response_t* response, const rc_api_
if (end > json && end[-1] == '\r')
--end;
if (end > json) {
char* dst = rc_buf_reserve(&response->buffer, (end - json) + 1);
response->error_message = dst;
memcpy(dst, json, end - json);
dst += (end - json);
*dst++ = '\0';
rc_buf_consume(&response->buffer, response->error_message, dst);
}
if (end > json)
response->error_message = rc_buffer_strncpy(&response->buffer, json, end - json);
response->succeeded = 0;
return RC_INVALID_JSON;
}
static int rc_json_convert_error_code(const char* server_error_code)
{
switch (server_error_code[0]) {
case 'a':
if (strcmp(server_error_code, "access_denied") == 0)
return RC_ACCESS_DENIED;
break;
case 'e':
if (strcmp(server_error_code, "expired_token") == 0)
return RC_EXPIRED_TOKEN;
break;
case 'i':
if (strcmp(server_error_code, "invalid_credentials") == 0)
return RC_INVALID_CREDENTIALS;
break;
default:
break;
}
return RC_API_FAILURE;
}
int rc_json_parse_server_response(rc_api_response_t* response, const rc_api_server_response_t* server_response, rc_json_field_t* fields, size_t field_count) {
int result;
@ -306,7 +318,38 @@ int rc_json_parse_server_response(rc_api_response_t* response, const rc_api_serv
response->error_message = NULL;
if (!server_response || !server_response->body || !*server_response->body) {
if (!server_response) {
response->succeeded = 0;
return RC_NO_RESPONSE;
}
if (server_response->http_status_code == RC_API_SERVER_RESPONSE_CLIENT_ERROR ||
server_response->http_status_code == RC_API_SERVER_RESPONSE_RETRYABLE_CLIENT_ERROR) {
/* client provided error message is passed as the response body */
response->error_message = server_response->body;
response->succeeded = 0;
return RC_NO_RESPONSE;
}
if (!server_response->body || !*server_response->body) {
/* expect valid HTTP status codes to have bodies that we can extract the message from,
* but provide some default messages in case they don't. */
switch (server_response->http_status_code) {
case 504: /* 504 Gateway Timeout */
case 522: /* 522 Connection Timed Out */
case 524: /* 524 A Timeout Occurred */
response->error_message = "Request has timed out.";
break;
case 521: /* 521 Web Server is Down */
case 523: /* 523 Origin is Unreachable */
response->error_message = "Could not connect to server.";
break;
default:
break;
}
response->succeeded = 0;
return RC_NO_RESPONSE;
}
@ -323,6 +366,13 @@ int rc_json_parse_server_response(rc_api_response_t* response, const rc_api_serv
rc_json_get_optional_string(&response->error_message, response, &fields[1], "Error", NULL);
rc_json_get_optional_bool(&response->succeeded, &fields[0], "Success", 1);
/* Code will be the third field in the fields array, but may not always be present */
if (field_count > 2 && strcmp(fields[2].name, "Code") == 0) {
rc_json_get_optional_string(&response->error_code, response, &fields[2], "Code", NULL);
if (response->error_code != NULL)
result = rc_json_convert_error_code(response->error_code);
}
}
return result;
@ -333,14 +383,14 @@ static int rc_json_missing_field(rc_api_response_t* response, const rc_json_fiel
const size_t not_found_len = strlen(not_found);
const size_t field_len = strlen(field->name);
char* write = rc_buf_reserve(&response->buffer, field_len + not_found_len + 1);
uint8_t* write = rc_buffer_reserve(&response->buffer, field_len + not_found_len + 1);
if (write) {
response->error_message = write;
response->error_message = (char*)write;
memcpy(write, field->name, field_len);
write += field_len;
memcpy(write, not_found, not_found_len + 1);
write += not_found_len + 1;
rc_buf_consume(&response->buffer, response->error_message, write);
rc_buffer_consume(&response->buffer, (uint8_t*)response->error_message, write);
}
response->succeeded = 0;
@ -383,18 +433,18 @@ static int rc_json_get_array_entry_value(rc_json_field_t* field, rc_json_iterato
return 1;
}
int rc_json_get_required_unum_array(unsigned** entries, unsigned* num_entries, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
int rc_json_get_required_unum_array(uint32_t** entries, uint32_t* num_entries, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
rc_json_iterator_t iterator;
rc_json_field_t array;
rc_json_field_t value;
unsigned* entry;
uint32_t* entry;
memset(&array, 0, sizeof(array));
if (!rc_json_get_required_array(num_entries, &array, response, field, field_name))
return RC_MISSING_VALUE;
if (*num_entries) {
*entries = (unsigned*)rc_buf_alloc(&response->buffer, *num_entries * sizeof(unsigned));
*entries = (uint32_t*)rc_buffer_alloc(&response->buffer, *num_entries * sizeof(uint32_t));
if (!*entries)
return RC_OUT_OF_MEMORY;
@ -419,7 +469,7 @@ int rc_json_get_required_unum_array(unsigned** entries, unsigned* num_entries, r
return RC_OK;
}
int rc_json_get_required_array(unsigned* num_entries, rc_json_field_t* array_field, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
int rc_json_get_required_array(uint32_t* num_entries, rc_json_field_t* array_field, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
#ifndef NDEBUG
if (strcmp(field->name, field_name) != 0)
return 0;
@ -431,7 +481,7 @@ int rc_json_get_required_array(unsigned* num_entries, rc_json_field_t* array_fie
return 1;
}
int rc_json_get_optional_array(unsigned* num_entries, rc_json_field_t* array_field, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
int rc_json_get_optional_array(uint32_t* num_entries, rc_json_field_t* array_field, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
#ifndef NDEBUG
if (strcmp(field->name, field_name) != 0)
return 0;
@ -468,16 +518,16 @@ int rc_json_get_array_entry_object(rc_json_field_t* fields, size_t field_count,
return 1;
}
static unsigned rc_json_decode_hex4(const char* input) {
static uint32_t rc_json_decode_hex4(const char* input) {
char hex[5];
memcpy(hex, input, 4);
hex[4] = '\0';
return (unsigned)strtoul(hex, NULL, 16);
return (uint32_t)strtoul(hex, NULL, 16);
}
static int rc_json_ucs32_to_utf8(unsigned char* dst, unsigned ucs32_char) {
static int rc_json_ucs32_to_utf8(uint8_t* dst, uint32_t ucs32_char) {
if (ucs32_char < 0x80) {
dst[0] = (ucs32_char & 0x7F);
return 1;
@ -522,7 +572,7 @@ static int rc_json_ucs32_to_utf8(unsigned char* dst, unsigned ucs32_char) {
return 6;
}
int rc_json_get_string(const char** out, rc_api_buffer_t* buffer, const rc_json_field_t* field, const char* field_name) {
int rc_json_get_string(const char** out, rc_buffer_t* buffer, const rc_json_field_t* field, const char* field_name) {
const char* src = field->value_start;
size_t len = field->value_end - field->value_start;
char* dst;
@ -553,7 +603,7 @@ int rc_json_get_string(const char** out, rc_api_buffer_t* buffer, const rc_json_
return 1;
}
*out = dst = rc_buf_reserve(buffer, len - 1); /* -2 for quotes, +1 for null terminator */
*out = dst = (char*)rc_buffer_reserve(buffer, len - 1); /* -2 for quotes, +1 for null terminator */
do {
if (*src == '\\') {
@ -574,13 +624,13 @@ int rc_json_get_string(const char** out, rc_api_buffer_t* buffer, const rc_json_
if (*src == 'u') {
/* unicode character */
unsigned ucs32_char = rc_json_decode_hex4(src + 1);
uint32_t ucs32_char = rc_json_decode_hex4(src + 1);
src += 5;
if (ucs32_char >= 0xD800 && ucs32_char < 0xE000) {
/* surrogate lead - look for surrogate tail */
if (ucs32_char < 0xDC00 && src[0] == '\\' && src[1] == 'u') {
const unsigned surrogate = rc_json_decode_hex4(src + 2);
const uint32_t surrogate = rc_json_decode_hex4(src + 2);
src += 6;
if (surrogate >= 0xDC00 && surrogate < 0xE000) {
@ -613,13 +663,13 @@ int rc_json_get_string(const char** out, rc_api_buffer_t* buffer, const rc_json_
} while (*src != '\"');
} else {
*out = dst = rc_buf_reserve(buffer, len + 1); /* +1 for null terminator */
*out = dst = (char*)rc_buffer_reserve(buffer, len + 1); /* +1 for null terminator */
memcpy(dst, src, len);
dst += len;
}
*dst++ = '\0';
rc_buf_consume(buffer, *out, dst);
rc_buffer_consume(buffer, (uint8_t*)(*out), (uint8_t*)dst);
return 1;
}
@ -635,9 +685,9 @@ int rc_json_get_required_string(const char** out, rc_api_response_t* response, c
return rc_json_missing_field(response, field);
}
int rc_json_get_num(int* out, const rc_json_field_t* field, const char* field_name) {
int rc_json_get_num(int32_t* out, const rc_json_field_t* field, const char* field_name) {
const char* src = field->value_start;
int value = 0;
int32_t value = 0;
int negative = 0;
#ifndef NDEBUG
@ -677,21 +727,21 @@ int rc_json_get_num(int* out, const rc_json_field_t* field, const char* field_na
return 1;
}
void rc_json_get_optional_num(int* out, const rc_json_field_t* field, const char* field_name, int default_value) {
void rc_json_get_optional_num(int32_t* out, const rc_json_field_t* field, const char* field_name, int default_value) {
if (!rc_json_get_num(out, field, field_name))
*out = default_value;
}
int rc_json_get_required_num(int* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
int rc_json_get_required_num(int32_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
if (rc_json_get_num(out, field, field_name))
return 1;
return rc_json_missing_field(response, field);
}
int rc_json_get_unum(unsigned* out, const rc_json_field_t* field, const char* field_name) {
int rc_json_get_unum(uint32_t* out, const rc_json_field_t* field, const char* field_name) {
const char* src = field->value_start;
int value = 0;
uint32_t value = 0;
#ifndef NDEBUG
if (strcmp(field->name, field_name) != 0)
@ -721,12 +771,12 @@ int rc_json_get_unum(unsigned* out, const rc_json_field_t* field, const char* fi
return 1;
}
void rc_json_get_optional_unum(unsigned* out, const rc_json_field_t* field, const char* field_name, unsigned default_value) {
void rc_json_get_optional_unum(uint32_t* out, const rc_json_field_t* field, const char* field_name, uint32_t default_value) {
if (!rc_json_get_unum(out, field, field_name))
*out = default_value;
}
int rc_json_get_required_unum(unsigned* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
int rc_json_get_required_unum(uint32_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
if (rc_json_get_unum(out, field, field_name))
return 1;
@ -819,133 +869,27 @@ int rc_json_get_required_bool(int* out, rc_api_response_t* response, const rc_js
return rc_json_missing_field(response, field);
}
/* --- rc_buf --- */
/* --- rc_api_request --- */
void rc_buf_init(rc_api_buffer_t* buffer) {
buffer->chunk.write = buffer->chunk.start = &buffer->data[0];
buffer->chunk.end = &buffer->data[sizeof(buffer->data)];
buffer->chunk.next = NULL;
}
void rc_buf_destroy(rc_api_buffer_t* buffer) {
rc_api_buffer_chunk_t *chunk;
#ifdef DEBUG_BUFFERS
int count = 0;
int wasted = 0;
int total = 0;
#endif
/* first chunk is not allocated. skip it. */
chunk = buffer->chunk.next;
/* deallocate any additional buffers */
while (chunk) {
rc_api_buffer_chunk_t* next = chunk->next;
#ifdef DEBUG_BUFFERS
total += (int)(chunk->end - chunk->data);
wasted += (int)(chunk->end - chunk->write);
++count;
#endif
free(chunk);
chunk = next;
}
#ifdef DEBUG_BUFFERS
printf("-- %d allocated buffers (%d/%d used, %d wasted, %0.2f%% efficiency)\n", count,
total - wasted, total, wasted, (float)(100.0 - (wasted * 100.0) / total));
#endif
}
char* rc_buf_reserve(rc_api_buffer_t* buffer, size_t amount) {
rc_api_buffer_chunk_t* chunk = &buffer->chunk;
size_t remaining;
while (chunk) {
remaining = chunk->end - chunk->write;
if (remaining >= amount)
return chunk->write;
if (!chunk->next) {
/* allocate a chunk of memory that is a multiple of 256-bytes. the first 32 bytes will be associated
* to the chunk header, and the remaining will be used for data.
*/
const size_t chunk_header_size = sizeof(rc_api_buffer_chunk_t);
const size_t alloc_size = (chunk_header_size + amount + 0xFF) & ~0xFF;
chunk->next = (rc_api_buffer_chunk_t*)malloc(alloc_size);
if (!chunk->next)
break;
chunk->next->start = (char*)chunk->next + chunk_header_size;
chunk->next->write = chunk->next->start;
chunk->next->end = (char*)chunk->next + alloc_size;
chunk->next->next = NULL;
}
chunk = chunk->next;
}
return NULL;
}
void rc_buf_consume(rc_api_buffer_t* buffer, const char* start, char* end) {
rc_api_buffer_chunk_t* chunk = &buffer->chunk;
do {
if (chunk->write == start) {
size_t offset = (end - chunk->start);
offset = (offset + 7) & ~7;
chunk->write = &chunk->start[offset];
if (chunk->write > chunk->end)
chunk->write = chunk->end;
break;
}
chunk = chunk->next;
} while (chunk);
}
void* rc_buf_alloc(rc_api_buffer_t* buffer, size_t amount) {
char* ptr = rc_buf_reserve(buffer, amount);
rc_buf_consume(buffer, ptr, ptr + amount);
return (void*)ptr;
}
char* rc_buf_strncpy(rc_api_buffer_t* buffer, const char* src, size_t len) {
char* dst = rc_buf_reserve(buffer, len + 1);
memcpy(dst, src, len);
dst[len] = '\0';
rc_buf_consume(buffer, dst, dst + len + 2);
return dst;
}
char* rc_buf_strcpy(rc_api_buffer_t* buffer, const char* src) {
return rc_buf_strncpy(buffer, src, strlen(src));
}
void rc_api_destroy_request(rc_api_request_t* request) {
rc_buf_destroy(&request->buffer);
}
void rc_api_format_md5(char checksum[33], const unsigned char digest[16]) {
snprintf(checksum, 33, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7],
digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]
);
void rc_api_destroy_request(rc_api_request_t* request)
{
rc_buffer_destroy(&request->buffer);
}
/* --- rc_url_builder --- */
void rc_url_builder_init(rc_api_url_builder_t* builder, rc_api_buffer_t* buffer, size_t estimated_size) {
rc_api_buffer_chunk_t* used_buffer;
void rc_url_builder_init(rc_api_url_builder_t* builder, rc_buffer_t* buffer, size_t estimated_size) {
rc_buffer_chunk_t* used_buffer;
memset(builder, 0, sizeof(*builder));
builder->buffer = buffer;
builder->write = builder->start = rc_buf_reserve(buffer, estimated_size);
builder->write = builder->start = (char*)rc_buffer_reserve(buffer, estimated_size);
used_buffer = &buffer->chunk;
while (used_buffer && used_buffer->write != builder->write)
while (used_buffer && used_buffer->write != (uint8_t*)builder->write)
used_buffer = used_buffer->next;
builder->end = (used_buffer) ? used_buffer->end : builder->start + estimated_size;
builder->end = (used_buffer) ? (char*)used_buffer->end : builder->start + estimated_size;
}
const char* rc_url_builder_finalize(rc_api_url_builder_t* builder) {
@ -954,7 +898,7 @@ const char* rc_url_builder_finalize(rc_api_url_builder_t* builder) {
if (builder->result != RC_OK)
return NULL;
rc_buf_consume(builder->buffer, builder->start, builder->write);
rc_buffer_consume(builder->buffer, (uint8_t*)builder->start, (uint8_t*)builder->write);
return builder->start;
}
@ -964,7 +908,7 @@ static int rc_url_builder_reserve(rc_api_url_builder_t* builder, size_t amount)
if (remaining < amount) {
const size_t used = builder->write - builder->start;
const size_t current_size = builder->end - builder->start;
const size_t buffer_prefix_size = sizeof(rc_api_buffer_chunk_t);
const size_t buffer_prefix_size = sizeof(rc_buffer_chunk_t);
char* new_start;
size_t new_size = (current_size < 256) ? 256 : current_size * 2;
do {
@ -975,11 +919,11 @@ static int rc_url_builder_reserve(rc_api_url_builder_t* builder, size_t amount)
new_size *= 2;
} while (1);
/* rc_buf_reserve will align to 256 bytes after including the buffer prefix. attempt to account for that */
/* rc_buffer_reserve will align to 256 bytes after including the buffer prefix. attempt to account for that */
if ((remaining - amount) > buffer_prefix_size)
new_size -= buffer_prefix_size;
new_start = rc_buf_reserve(builder->buffer, new_size);
new_start = (char*)rc_buffer_reserve(builder->buffer, new_size);
if (!new_start) {
builder->result = RC_OUT_OF_MEMORY;
return RC_OUT_OF_MEMORY;
@ -1070,7 +1014,7 @@ static int rc_url_builder_append_param_equals(rc_api_url_builder_t* builder, con
return builder->result;
}
void rc_url_builder_append_unum_param(rc_api_url_builder_t* builder, const char* param, unsigned value) {
void rc_url_builder_append_unum_param(rc_api_url_builder_t* builder, const char* param, uint32_t value) {
if (rc_url_builder_append_param_equals(builder, param) == RC_OK) {
char num[16];
int chars = snprintf(num, sizeof(num), "%u", value);
@ -1078,7 +1022,7 @@ void rc_url_builder_append_unum_param(rc_api_url_builder_t* builder, const char*
}
}
void rc_url_builder_append_num_param(rc_api_url_builder_t* builder, const char* param, int value) {
void rc_url_builder_append_num_param(rc_api_url_builder_t* builder, const char* param, int32_t value) {
if (rc_url_builder_append_param_equals(builder, param) == RC_OK) {
char num[16];
int chars = snprintf(num, sizeof(num), "%d", value);
@ -1093,7 +1037,7 @@ void rc_url_builder_append_str_param(rc_api_url_builder_t* builder, const char*
void rc_api_url_build_dorequest_url(rc_api_request_t* request) {
#define DOREQUEST_ENDPOINT "/dorequest.php"
rc_buf_init(&request->buffer);
rc_buffer_init(&request->buffer);
if (!g_host) {
request->url = RETROACHIEVEMENTS_HOST DOREQUEST_ENDPOINT;
@ -1102,13 +1046,13 @@ void rc_api_url_build_dorequest_url(rc_api_request_t* request) {
const size_t endpoint_len = sizeof(DOREQUEST_ENDPOINT);
const size_t host_len = strlen(g_host);
const size_t url_len = host_len + endpoint_len;
char* url = rc_buf_reserve(&request->buffer, url_len);
uint8_t* url = rc_buffer_reserve(&request->buffer, url_len);
memcpy(url, g_host, host_len);
memcpy(url + host_len, DOREQUEST_ENDPOINT, endpoint_len);
rc_buf_consume(&request->buffer, url, url + url_len);
rc_buffer_consume(&request->buffer, url, url + url_len);
request->url = url;
request->url = (char*)url;
}
#undef DOREQUEST_ENDPOINT
}
@ -1182,7 +1126,7 @@ void rc_api_set_image_host(const char* hostname) {
int rc_api_init_fetch_image_request(rc_api_request_t* request, const rc_api_fetch_image_request_t* api_params) {
rc_api_url_builder_t builder;
rc_buf_init(&request->buffer);
rc_buffer_init(&request->buffer);
rc_url_builder_init(&builder, &request->buffer, 64);
if (g_imagehost) {

View File

@ -16,13 +16,13 @@ typedef struct rc_api_url_builder_t {
char* write;
char* start;
char* end;
/* pointer to a preallocated rc_api_buffer_t */
rc_api_buffer_t* buffer;
/* pointer to a preallocated rc_buffer_t */
rc_buffer_t* buffer;
int result;
}
rc_api_url_builder_t;
void rc_url_builder_init(rc_api_url_builder_t* builder, rc_api_buffer_t* buffer, size_t estimated_size);
void rc_url_builder_init(rc_api_url_builder_t* builder, rc_buffer_t* buffer, size_t estimated_size);
void rc_url_builder_append(rc_api_url_builder_t* builder, const char* data, size_t len);
const char* rc_url_builder_finalize(rc_api_url_builder_t* builder);
@ -33,7 +33,7 @@ typedef struct rc_json_field_t {
const char* value_end;
const char* name;
size_t name_len;
unsigned array_size;
uint32_t array_size;
}
rc_json_field_t;
@ -44,44 +44,35 @@ typedef struct rc_json_iterator_t {
rc_json_iterator_t;
int rc_json_parse_server_response(rc_api_response_t* response, const rc_api_server_response_t* server_response, rc_json_field_t* fields, size_t field_count);
int rc_json_get_string(const char** out, rc_api_buffer_t* buffer, const rc_json_field_t* field, const char* field_name);
int rc_json_get_num(int* out, const rc_json_field_t* field, const char* field_name);
int rc_json_get_unum(unsigned* out, const rc_json_field_t* field, const char* field_name);
int rc_json_get_string(const char** out, rc_buffer_t* buffer, const rc_json_field_t* field, const char* field_name);
int rc_json_get_num(int32_t* out, const rc_json_field_t* field, const char* field_name);
int rc_json_get_unum(uint32_t* out, const rc_json_field_t* field, const char* field_name);
int rc_json_get_bool(int* out, const rc_json_field_t* field, const char* field_name);
int rc_json_get_datetime(time_t* out, const rc_json_field_t* field, const char* field_name);
void rc_json_get_optional_string(const char** out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name, const char* default_value);
void rc_json_get_optional_num(int* out, const rc_json_field_t* field, const char* field_name, int default_value);
void rc_json_get_optional_unum(unsigned* out, const rc_json_field_t* field, const char* field_name, unsigned default_value);
void rc_json_get_optional_num(int32_t* out, const rc_json_field_t* field, const char* field_name, int default_value);
void rc_json_get_optional_unum(uint32_t* out, const rc_json_field_t* field, const char* field_name, uint32_t default_value);
void rc_json_get_optional_bool(int* out, const rc_json_field_t* field, const char* field_name, int default_value);
int rc_json_get_optional_array(unsigned* num_entries, rc_json_field_t* iterator, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_optional_array(uint32_t* num_entries, rc_json_field_t* iterator, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_string(const char** out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_num(int* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_unum(unsigned* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_num(int32_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_unum(uint32_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_bool(int* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_datetime(time_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_object(rc_json_field_t* fields, size_t field_count, rc_api_response_t* response, rc_json_field_t* field, const char* field_name);
int rc_json_get_required_unum_array(unsigned** entries, unsigned* num_entries, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_array(unsigned* num_entries, rc_json_field_t* array_field, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_unum_array(uint32_t** entries, uint32_t* num_entries, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_array(uint32_t* num_entries, rc_json_field_t* array_field, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_array_entry_object(rc_json_field_t* fields, size_t field_count, rc_json_iterator_t* iterator);
int rc_json_get_next_object_field(rc_json_iterator_t* iterator, rc_json_field_t* field);
int rc_json_get_object_string_length(const char* json);
void rc_buf_init(rc_api_buffer_t* buffer);
void rc_buf_destroy(rc_api_buffer_t* buffer);
char* rc_buf_reserve(rc_api_buffer_t* buffer, size_t amount);
void rc_buf_consume(rc_api_buffer_t* buffer, const char* start, char* end);
void* rc_buf_alloc(rc_api_buffer_t* buffer, size_t amount);
char* rc_buf_strcpy(rc_api_buffer_t* buffer, const char* src);
char* rc_buf_strncpy(rc_api_buffer_t* buffer, const char* src, size_t len);
void rc_url_builder_append_encoded_str(rc_api_url_builder_t* builder, const char* str);
void rc_url_builder_append_num_param(rc_api_url_builder_t* builder, const char* param, int value);
void rc_url_builder_append_unum_param(rc_api_url_builder_t* builder, const char* param, unsigned value);
void rc_url_builder_append_num_param(rc_api_url_builder_t* builder, const char* param, int32_t value);
void rc_url_builder_append_unum_param(rc_api_url_builder_t* builder, const char* param, uint32_t value);
void rc_url_builder_append_str_param(rc_api_url_builder_t* builder, const char* param, const char* value);
void rc_api_url_build_dorequest_url(rc_api_request_t* request);
int rc_api_url_build_dorequest(rc_api_url_builder_t* builder, const char* api, const char* username, const char* api_token);
void rc_api_format_md5(char checksum[33], const unsigned char digest[16]);
#ifdef __cplusplus
}

View File

@ -1,7 +1,7 @@
#include "rc_api_editor.h"
#include "rc_api_common.h"
#include "../rcheevos/rc_compat.h"
#include "../rc_compat.h"
#include "../rhash/md5.h"
#include <stdlib.h>
@ -60,7 +60,7 @@ int rc_api_process_fetch_code_notes_server_response(rc_api_fetch_code_notes_resp
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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 || !response->response.succeeded)
@ -70,7 +70,7 @@ int rc_api_process_fetch_code_notes_server_response(rc_api_fetch_code_notes_resp
return RC_MISSING_VALUE;
if (response->num_notes) {
response->notes = (rc_api_code_note_t*)rc_buf_alloc(&response->response.buffer, response->num_notes * sizeof(rc_api_code_note_t));
response->notes = (rc_api_code_note_t*)rc_buffer_alloc(&response->response.buffer, response->num_notes * sizeof(rc_api_code_note_t));
if (!response->notes)
return RC_OUT_OF_MEMORY;
@ -117,7 +117,7 @@ int rc_api_process_fetch_code_notes_server_response(rc_api_fetch_code_notes_resp
}
void rc_api_destroy_fetch_code_notes_response(rc_api_fetch_code_notes_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}
/* --- Update Code Note --- */
@ -170,7 +170,7 @@ int rc_api_process_update_code_note_server_response(rc_api_update_code_note_resp
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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 || !response->response.succeeded)
@ -180,7 +180,7 @@ int rc_api_process_update_code_note_server_response(rc_api_update_code_note_resp
}
void rc_api_destroy_update_code_note_response(rc_api_update_code_note_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}
/* --- Update Achievement --- */
@ -231,7 +231,7 @@ int rc_api_init_update_achievement_request(rc_api_request_t* request, const rc_a
snprintf(buffer, sizeof(buffer), "%u", api_params->points * 3);
md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer));
md5_finish(&md5, hash);
rc_api_format_md5(buffer, hash);
rc_format_md5(buffer, hash);
rc_url_builder_append_str_param(&builder, "h", buffer);
request->post_data = rc_url_builder_finalize(&builder);
@ -260,7 +260,7 @@ int rc_api_process_update_achievement_server_response(rc_api_update_achievement_
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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 || !response->response.succeeded)
@ -273,7 +273,7 @@ int rc_api_process_update_achievement_server_response(rc_api_update_achievement_
}
void rc_api_destroy_update_achievement_response(rc_api_update_achievement_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}
/* --- Update Leaderboard --- */
@ -333,7 +333,7 @@ int rc_api_init_update_leaderboard_request(rc_api_request_t* request, const rc_a
md5_append(&md5, (md5_byte_t*)"RE2", 3);
md5_append(&md5, (md5_byte_t*)api_params->format, (int)strlen(api_params->format));
md5_finish(&md5, hash);
rc_api_format_md5(buffer, hash);
rc_format_md5(buffer, hash);
rc_url_builder_append_str_param(&builder, "h", buffer);
request->post_data = rc_url_builder_finalize(&builder);
@ -362,7 +362,7 @@ int rc_api_process_update_leaderboard_server_response(rc_api_update_leaderboard_
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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 || !response->response.succeeded)
@ -375,7 +375,7 @@ int rc_api_process_update_leaderboard_server_response(rc_api_update_leaderboard_
}
void rc_api_destroy_update_leaderboard_response(rc_api_update_leaderboard_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}
/* --- Fetch Badge Range --- */
@ -417,7 +417,7 @@ int rc_api_process_fetch_badge_range_server_response(rc_api_fetch_badge_range_re
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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 || !response->response.succeeded)
@ -432,7 +432,7 @@ int rc_api_process_fetch_badge_range_server_response(rc_api_fetch_badge_range_re
}
void rc_api_destroy_fetch_badge_range_response(rc_api_fetch_badge_range_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}
/* --- Add Game Hash --- */
@ -498,7 +498,7 @@ int rc_api_process_add_game_hash_server_response(rc_api_add_game_hash_response_t
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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 || !response->response.succeeded)
@ -514,5 +514,5 @@ int rc_api_process_add_game_hash_server_response(rc_api_add_game_hash_response_t
}
void rc_api_destroy_add_game_hash_response(rc_api_add_game_hash_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}

View File

@ -47,7 +47,7 @@ int rc_api_process_fetch_achievement_info_server_response(rc_api_fetch_achieveme
rc_api_achievement_awarded_entry_t* entry;
rc_json_field_t array_field;
rc_json_iterator_t iterator;
unsigned timet;
uint32_t timet;
int result;
rc_json_field_t fields[] = {
@ -75,7 +75,7 @@ int rc_api_process_fetch_achievement_info_server_response(rc_api_fetch_achieveme
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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)
@ -97,7 +97,7 @@ int rc_api_process_fetch_achievement_info_server_response(rc_api_fetch_achieveme
return RC_MISSING_VALUE;
if (response->num_recently_awarded) {
response->recently_awarded = (rc_api_achievement_awarded_entry_t*)rc_buf_alloc(&response->response.buffer, response->num_recently_awarded * sizeof(rc_api_achievement_awarded_entry_t));
response->recently_awarded = (rc_api_achievement_awarded_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_recently_awarded * sizeof(rc_api_achievement_awarded_entry_t));
if (!response->recently_awarded)
return RC_OUT_OF_MEMORY;
@ -122,7 +122,7 @@ int rc_api_process_fetch_achievement_info_server_response(rc_api_fetch_achieveme
}
void rc_api_destroy_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}
/* --- Fetch Leaderboard Info --- */
@ -165,7 +165,7 @@ int rc_api_process_fetch_leaderboard_info_server_response(rc_api_fetch_leaderboa
rc_api_lboard_info_entry_t* entry;
rc_json_field_t array_field;
rc_json_iterator_t iterator;
unsigned timet;
uint32_t timet;
int result;
size_t len;
char format[16];
@ -206,7 +206,7 @@ int rc_api_process_fetch_leaderboard_info_server_response(rc_api_fetch_leaderboa
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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)
@ -217,7 +217,7 @@ int rc_api_process_fetch_leaderboard_info_server_response(rc_api_fetch_leaderboa
if (!rc_json_get_required_unum(&response->id, &response->response, &leaderboarddata_fields[0], "LBID"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_num(&response->lower_is_better, &response->response, &leaderboarddata_fields[2], "LowerIsBetter"))
if (!rc_json_get_required_unum(&response->lower_is_better, &response->response, &leaderboarddata_fields[2], "LowerIsBetter"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_string(&response->title, &response->response, &leaderboarddata_fields[3], "LBTitle"))
return RC_MISSING_VALUE;
@ -250,7 +250,7 @@ int rc_api_process_fetch_leaderboard_info_server_response(rc_api_fetch_leaderboa
return RC_MISSING_VALUE;
if (response->num_entries) {
response->entries = (rc_api_lboard_info_entry_t*)rc_buf_alloc(&response->response.buffer, response->num_entries * sizeof(rc_api_lboard_info_entry_t));
response->entries = (rc_api_lboard_info_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_entries * sizeof(rc_api_lboard_info_entry_t));
if (!response->entries)
return RC_OUT_OF_MEMORY;
@ -284,7 +284,7 @@ int rc_api_process_fetch_leaderboard_info_server_response(rc_api_fetch_leaderboa
}
void rc_api_destroy_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}
/* --- Fetch Games List --- */
@ -331,7 +331,7 @@ int rc_api_process_fetch_games_list_server_response(rc_api_fetch_games_list_resp
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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)
@ -344,9 +344,9 @@ int rc_api_process_fetch_games_list_server_response(rc_api_fetch_games_list_resp
}
response->num_entries = fields[2].array_size;
rc_buf_reserve(&response->response.buffer, response->num_entries * (32 + sizeof(rc_api_game_list_entry_t)));
rc_buffer_reserve(&response->response.buffer, response->num_entries * (32 + sizeof(rc_api_game_list_entry_t)));
response->entries = (rc_api_game_list_entry_t*)rc_buf_alloc(&response->response.buffer, response->num_entries * sizeof(rc_api_game_list_entry_t));
response->entries = (rc_api_game_list_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_entries * sizeof(rc_api_game_list_entry_t));
if (!response->entries)
return RC_OUT_OF_MEMORY;
@ -369,5 +369,5 @@ int rc_api_process_fetch_games_list_server_response(rc_api_fetch_games_list_resp
}
void rc_api_destroy_fetch_games_list_response(rc_api_fetch_games_list_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}

View File

@ -3,7 +3,7 @@
#include "rc_runtime.h"
#include "rc_runtime_types.h"
#include "../rcheevos/rc_compat.h"
#include "../rc_compat.h"
#include "../rhash/md5.h"
#include <stdlib.h>
@ -48,7 +48,7 @@ int rc_api_process_resolve_hash_server_response(rc_api_resolve_hash_response_t*
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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)
@ -59,7 +59,7 @@ int rc_api_process_resolve_hash_server_response(rc_api_resolve_hash_response_t*
}
void rc_api_destroy_resolve_hash_response(rc_api_resolve_hash_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}
/* --- Fetch Game Data --- */
@ -102,7 +102,7 @@ int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_respon
const char* last_author_field = "";
size_t last_author_len = 0;
size_t len;
unsigned timet;
uint32_t timet;
int result;
char format[16];
@ -150,7 +150,7 @@ int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_respon
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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 || !response->response.succeeded)
@ -191,7 +191,7 @@ int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_respon
len += (patchdata_fields[6].value_end - patchdata_fields[6].value_start) - /* leaderboards */
patchdata_fields[6].array_size * (60 - sizeof(rc_api_leaderboard_definition_t));
rc_buf_reserve(&response->response.buffer, len);
rc_buffer_reserve(&response->response.buffer, len);
/* end estimation */
rc_json_get_optional_string(&response->rich_presence_script, &response->response, &patchdata_fields[4], "RichPresencePatch", "");
@ -202,7 +202,7 @@ int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_respon
return RC_MISSING_VALUE;
if (response->num_achievements) {
response->achievements = (rc_api_achievement_definition_t*)rc_buf_alloc(&response->response.buffer, response->num_achievements * sizeof(rc_api_achievement_definition_t));
response->achievements = (rc_api_achievement_definition_t*)rc_buffer_alloc(&response->response.buffer, response->num_achievements * sizeof(rc_api_achievement_definition_t));
if (!response->achievements)
return RC_OUT_OF_MEMORY;
@ -255,7 +255,7 @@ int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_respon
return RC_MISSING_VALUE;
if (response->num_leaderboards) {
response->leaderboards = (rc_api_leaderboard_definition_t*)rc_buf_alloc(&response->response.buffer, response->num_leaderboards * sizeof(rc_api_leaderboard_definition_t));
response->leaderboards = (rc_api_leaderboard_definition_t*)rc_buffer_alloc(&response->response.buffer, response->num_leaderboards * sizeof(rc_api_leaderboard_definition_t));
if (!response->leaderboards)
return RC_OUT_OF_MEMORY;
@ -273,8 +273,10 @@ int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_respon
return RC_MISSING_VALUE;
if (!rc_json_get_required_string(&leaderboard->definition, &response->response, &leaderboard_fields[3], "Mem"))
return RC_MISSING_VALUE;
rc_json_get_optional_bool(&leaderboard->lower_is_better, &leaderboard_fields[5], "LowerIsBetter", 0);
rc_json_get_optional_bool(&leaderboard->hidden, &leaderboard_fields[6], "Hidden", 0);
rc_json_get_optional_bool(&result, &leaderboard_fields[5], "LowerIsBetter", 0);
leaderboard->lower_is_better = (uint8_t)result;
rc_json_get_optional_bool(&result, &leaderboard_fields[6], "Hidden", 0);
leaderboard->hidden = (uint8_t)result;
if (!leaderboard_fields[4].value_end)
return RC_MISSING_VALUE;
@ -296,7 +298,7 @@ int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_respon
}
void rc_api_destroy_fetch_game_data_response(rc_api_fetch_game_data_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}
/* --- Ping --- */
@ -340,13 +342,13 @@ int rc_api_process_ping_server_response(rc_api_ping_response_t* response, const
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
rc_buffer_init(&response->response.buffer);
return rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0]));
}
void rc_api_destroy_ping_response(rc_api_ping_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}
/* --- Award Achievement --- */
@ -377,7 +379,7 @@ int rc_api_init_award_achievement_request(rc_api_request_t* request, const rc_ap
snprintf(buffer, sizeof(buffer), "%d", api_params->hardcore ? 1 : 0);
md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer));
md5_finish(&md5, digest);
rc_api_format_md5(buffer, digest);
rc_format_md5(buffer, digest);
rc_url_builder_append_str_param(&builder, "v", buffer);
request->post_data = rc_url_builder_finalize(&builder);
@ -409,7 +411,7 @@ int rc_api_process_award_achievement_server_response(rc_api_award_achievement_re
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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)
@ -437,7 +439,7 @@ int rc_api_process_award_achievement_server_response(rc_api_award_achievement_re
}
void rc_api_destroy_award_achievement_response(rc_api_award_achievement_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}
/* --- Submit Leaderboard Entry --- */
@ -469,7 +471,7 @@ int rc_api_init_submit_lboard_entry_request(rc_api_request_t* request, const rc_
snprintf(buffer, sizeof(buffer), "%d", api_params->score);
md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer));
md5_finish(&md5, digest);
rc_api_format_md5(buffer, digest);
rc_format_md5(buffer, digest);
rc_url_builder_append_str_param(&builder, "v", buffer);
request->post_data = rc_url_builder_finalize(&builder);
@ -543,7 +545,7 @@ int rc_api_process_submit_lboard_entry_server_response(rc_api_submit_lboard_entr
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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 || !response->response.succeeded)
@ -568,7 +570,7 @@ int rc_api_process_submit_lboard_entry_server_response(rc_api_submit_lboard_entr
return RC_MISSING_VALUE;
if (response->num_top_entries) {
response->top_entries = (rc_api_lboard_entry_t*)rc_buf_alloc(&response->response.buffer, response->num_top_entries * sizeof(rc_api_lboard_entry_t));
response->top_entries = (rc_api_lboard_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_top_entries * sizeof(rc_api_lboard_entry_t));
if (!response->top_entries)
return RC_OUT_OF_MEMORY;
@ -595,5 +597,5 @@ int rc_api_process_submit_lboard_entry_server_response(rc_api_submit_lboard_entr
}
void rc_api_destroy_submit_lboard_entry_response(rc_api_submit_lboard_entry_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}

View File

@ -1,7 +1,7 @@
#include "rc_api_user.h"
#include "rc_api_common.h"
#include "../rcheevos/rc_version.h"
#include "../rc_version.h"
#include <string.h>
@ -16,7 +16,7 @@ int rc_api_init_login_request(rc_api_request_t* request, const rc_api_login_requ
return RC_INVALID_STATE;
rc_url_builder_init(&builder, &request->buffer, 48);
rc_url_builder_append_str_param(&builder, "r", "login");
rc_url_builder_append_str_param(&builder, "r", "login2");
rc_url_builder_append_str_param(&builder, "u", api_params->username);
if (api_params->password && api_params->password[0])
@ -47,6 +47,7 @@ int rc_api_process_login_server_response(rc_api_login_response_t* response, cons
rc_json_field_t fields[] = {
RC_JSON_NEW_FIELD("Success"),
RC_JSON_NEW_FIELD("Error"),
RC_JSON_NEW_FIELD("Code"),
RC_JSON_NEW_FIELD("User"),
RC_JSON_NEW_FIELD("Token"),
RC_JSON_NEW_FIELD("Score"),
@ -56,28 +57,28 @@ int rc_api_process_login_server_response(rc_api_login_response_t* response, cons
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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 || !response->response.succeeded)
return result;
if (!rc_json_get_required_string(&response->username, &response->response, &fields[2], "User"))
if (!rc_json_get_required_string(&response->username, &response->response, &fields[3], "User"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_string(&response->api_token, &response->response, &fields[3], "Token"))
if (!rc_json_get_required_string(&response->api_token, &response->response, &fields[4], "Token"))
return RC_MISSING_VALUE;
rc_json_get_optional_unum(&response->score, &fields[4], "Score", 0);
rc_json_get_optional_unum(&response->score_softcore, &fields[5], "SoftcoreScore", 0);
rc_json_get_optional_unum(&response->num_unread_messages, &fields[6], "Messages", 0);
rc_json_get_optional_unum(&response->score, &fields[5], "Score", 0);
rc_json_get_optional_unum(&response->score_softcore, &fields[6], "SoftcoreScore", 0);
rc_json_get_optional_unum(&response->num_unread_messages, &fields[7], "Messages", 0);
rc_json_get_optional_string(&response->display_name, &response->response, &fields[7], "DisplayName", response->username);
rc_json_get_optional_string(&response->display_name, &response->response, &fields[8], "DisplayName", response->username);
return RC_OK;
}
void rc_api_destroy_login_response(rc_api_login_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}
/* --- Start Session --- */
@ -115,7 +116,7 @@ int rc_api_process_start_session_server_response(rc_api_start_session_response_t
rc_api_unlock_entry_t* unlock;
rc_json_field_t array_field;
rc_json_iterator_t iterator;
unsigned timet;
uint32_t timet;
int result;
rc_json_field_t fields[] = {
@ -132,14 +133,14 @@ int rc_api_process_start_session_server_response(rc_api_start_session_response_t
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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 || !response->response.succeeded)
return result;
if (rc_json_get_optional_array(&response->num_unlocks, &array_field, &response->response, &fields[2], "Unlocks") && response->num_unlocks) {
response->unlocks = (rc_api_unlock_entry_t*)rc_buf_alloc(&response->response.buffer, response->num_unlocks * sizeof(rc_api_unlock_entry_t));
response->unlocks = (rc_api_unlock_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_unlocks * sizeof(rc_api_unlock_entry_t));
if (!response->unlocks)
return RC_OUT_OF_MEMORY;
@ -160,7 +161,7 @@ int rc_api_process_start_session_server_response(rc_api_start_session_response_t
}
if (rc_json_get_optional_array(&response->num_hardcore_unlocks, &array_field, &response->response, &fields[3], "HardcoreUnlocks") && response->num_hardcore_unlocks) {
response->hardcore_unlocks = (rc_api_unlock_entry_t*)rc_buf_alloc(&response->response.buffer, response->num_hardcore_unlocks * sizeof(rc_api_unlock_entry_t));
response->hardcore_unlocks = (rc_api_unlock_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_hardcore_unlocks * sizeof(rc_api_unlock_entry_t));
if (!response->hardcore_unlocks)
return RC_OUT_OF_MEMORY;
@ -187,7 +188,7 @@ int rc_api_process_start_session_server_response(rc_api_start_session_response_t
}
void rc_api_destroy_start_session_response(rc_api_start_session_response_t* response) {
rc_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}
/* --- Fetch User Unlocks --- */
@ -231,7 +232,7 @@ int rc_api_process_fetch_user_unlocks_server_response(rc_api_fetch_user_unlocks_
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
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 || !response->response.succeeded)
@ -242,5 +243,5 @@ 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_buf_destroy(&response->response.buffer);
rc_buffer_destroy(&response->response.buffer);
}

View File

@ -4,10 +4,11 @@
#include "rc_api_runtime.h"
#include "rc_api_user.h"
#include "rc_consoles.h"
#include "rc_internal.h"
#include "rc_hash.h"
#include "../rapi/rc_api_common.h"
#include "rapi/rc_api_common.h"
#include "rcheevos/rc_internal.h"
#include <stdarg.h>
@ -26,6 +27,12 @@ struct rc_client_async_handle_t {
uint8_t aborted;
};
enum {
RC_CLIENT_ASYNC_NOT_ABORTED = 0,
RC_CLIENT_ASYNC_ABORTED = 1,
RC_CLIENT_ASYNC_DESTROYED = 2
};
typedef struct rc_client_generic_callback_data_t {
rc_client_t* client;
rc_client_callback_t callback;
@ -71,7 +78,6 @@ static rc_client_async_handle_t* rc_client_load_game(rc_client_load_state_t* loa
static void rc_client_ping(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now);
static void rc_client_raise_leaderboard_events(rc_client_t* client, rc_client_subset_info_t* subset);
static void rc_client_raise_pending_events(rc_client_t* client, rc_client_game_info_t* game);
static void rc_client_release_leaderboard_tracker(rc_client_game_info_t* game, rc_client_leaderboard_info_t* leaderboard);
static void rc_client_reschedule_callback(rc_client_t* client, rc_client_scheduled_callback_data_t* callback, rc_clock_t when);
static void rc_client_award_achievement_retry(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now);
static void rc_client_submit_leaderboard_entry_retry(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now);
@ -98,7 +104,7 @@ rc_client_t* rc_client_create(rc_client_read_memory_func_t read_memory_function,
rc_mutex_init(&client->state.mutex);
rc_buf_init(&client->state.buffer);
rc_buffer_init(&client->state.buffer);
return client;
}
@ -108,9 +114,24 @@ void rc_client_destroy(rc_client_t* client)
if (!client)
return;
rc_mutex_lock(&client->state.mutex);
{
size_t i;
for (i = 0; i < sizeof(client->state.async_handles) / sizeof(client->state.async_handles[0]); ++i) {
if (client->state.async_handles[i])
client->state.async_handles[i]->aborted = RC_CLIENT_ASYNC_DESTROYED;
}
if (client->state.load) {
client->state.load->async_handle.aborted = RC_CLIENT_ASYNC_DESTROYED;
client->state.load = NULL;
}
}
rc_mutex_unlock(&client->state.mutex);
rc_client_unload_game(client);
rc_buf_destroy(&client->state.buffer);
rc_buffer_destroy(&client->state.buffer);
rc_mutex_destroy(&client->state.mutex);
@ -272,13 +293,39 @@ void rc_client_set_get_time_millisecs_function(rc_client_t* client, rc_get_time_
client->callbacks.get_time_millisecs = handler ? handler : rc_client_clock_get_now_millisecs;
}
static int rc_client_async_handle_aborted(rc_client_t* client, rc_client_async_handle_t* async_handle)
static void rc_client_begin_async(rc_client_t* client, rc_client_async_handle_t* async_handle)
{
int aborted;
size_t i;
rc_mutex_lock(&client->state.mutex);
aborted = async_handle->aborted;
for (i = 0; i < sizeof(client->state.async_handles) / sizeof(client->state.async_handles[0]); ++i) {
if (!client->state.async_handles[i]) {
client->state.async_handles[i] = async_handle;
break;
}
}
rc_mutex_unlock(&client->state.mutex);
}
static int rc_client_end_async(rc_client_t* client, rc_client_async_handle_t* async_handle)
{
int aborted = async_handle->aborted;
/* if client was destroyed, mutex doesn't exist and we don't need to remove the handle from the collection */
if (aborted != RC_CLIENT_ASYNC_DESTROYED) {
size_t i;
rc_mutex_lock(&client->state.mutex);
for (i = 0; i < sizeof(client->state.async_handles) / sizeof(client->state.async_handles[0]); ++i) {
if (client->state.async_handles[i] == async_handle) {
client->state.async_handles[i] = NULL;
break;
}
}
aborted = async_handle->aborted;
rc_mutex_unlock(&client->state.mutex);
}
return aborted;
}
@ -287,7 +334,7 @@ void rc_client_abort_async(rc_client_t* client, rc_client_async_handle_t* async_
{
if (async_handle && client) {
rc_mutex_lock(&client->state.mutex);
async_handle->aborted = 1;
async_handle->aborted = RC_CLIENT_ASYNC_ABORTED;
rc_mutex_unlock(&client->state.mutex);
}
}
@ -311,13 +358,16 @@ static const char* rc_client_server_error_message(int* result, int http_status_c
return NULL;
}
static void rc_client_raise_server_error_event(rc_client_t* client, const char* api, const char* error_message)
static void rc_client_raise_server_error_event(rc_client_t* client,
const char* api, uint32_t related_id, int result, const char* error_message)
{
rc_client_server_error_t server_error;
rc_client_event_t client_event;
server_error.api = api;
server_error.error_message = error_message;
server_error.result = result;
server_error.related_id = related_id;
memset(&client_event, 0, sizeof(client_event));
client_event.type = RC_CLIENT_EVENT_SERVER_ERROR;
@ -380,11 +430,15 @@ static int rc_client_should_retry(const rc_api_server_response_t* server_respons
{
switch (server_response->http_status_code) {
case 502: /* 502 Bad Gateway */
/* nginx connection pool full. retry */
/* nginx connection pool full */
return 1;
case 503: /* 503 Service Temporarily Unavailable */
/* site is in maintenance mode. retry */
/* site is in maintenance mode */
return 1;
case 504: /* 504 Gateway Timeout */
/* timeout between web server and database server */
return 1;
case 429: /* 429 Too Many Requests */
@ -407,7 +461,19 @@ static int rc_client_should_retry(const rc_api_server_response_t* server_respons
/* connection to server from cloudfare was dropped before request was completed */
return 1;
case RC_API_SERVER_RESPONSE_RETRYABLE_CLIENT_ERROR:
/* client provided non-HTTP error (explicitly retryable) */
return 1;
case RC_API_SERVER_RESPONSE_CLIENT_ERROR:
/* client provided non-HTTP error (implicitly non-retryable) */
return 0;
default:
/* assume any error not handled above where no response was received should be retried */
if (server_response->body_length == 0 || !server_response->body || !server_response->body[0])
return 1;
return 0;
}
}
@ -443,8 +509,11 @@ static void rc_client_login_callback(const rc_api_server_response_t* server_resp
const char* error_message;
int result;
if (rc_client_async_handle_aborted(client, &login_callback_data->async_handle)) {
RC_CLIENT_LOG_VERBOSE(client, "Login aborted");
result = rc_client_end_async(client, &login_callback_data->async_handle);
if (result) {
if (result != RC_CLIENT_ASYNC_DESTROYED)
rc_client_logout(client); /* logout will reset the user state and call the load game callback */
free(login_callback_data);
return;
}
@ -455,6 +524,7 @@ static void rc_client_login_callback(const rc_api_server_response_t* server_resp
login_callback_data->callback(RC_ABORTED, "Login aborted", client, login_callback_data->callback_userdata);
free(login_callback_data);
/* logout call will immediately abort load game before this callback gets called */
return;
}
@ -474,14 +544,14 @@ static void rc_client_login_callback(const rc_api_server_response_t* server_resp
rc_client_begin_fetch_game_data(load_state);
}
else {
client->user.username = rc_buf_strcpy(&client->state.buffer, login_response.username);
client->user.username = rc_buffer_strcpy(&client->state.buffer, login_response.username);
if (strcmp(login_response.username, login_response.display_name) == 0)
client->user.display_name = client->user.username;
else
client->user.display_name = rc_buf_strcpy(&client->state.buffer, login_response.display_name);
client->user.display_name = rc_buffer_strcpy(&client->state.buffer, login_response.display_name);
client->user.token = rc_buf_strcpy(&client->state.buffer, login_response.api_token);
client->user.token = rc_buffer_strcpy(&client->state.buffer, login_response.api_token);
client->user.score = login_response.score;
client->user.score_softcore = login_response.score_softcore;
client->user.num_unread_messages = login_response.num_unread_messages;
@ -539,7 +609,9 @@ static rc_client_async_handle_t* rc_client_begin_login(rc_client_t* client,
callback_data->callback = callback;
callback_data->callback_userdata = callback_userdata;
rc_client_begin_async(client, &callback_data->async_handle);
client->callbacks.server_call(&request, rc_client_login_callback, callback_data, client);
rc_api_destroy_request(&request);
return &callback_data->async_handle;
@ -702,7 +774,7 @@ static void rc_client_free_game(rc_client_game_info_t* game)
{
rc_runtime_destroy(&game->runtime);
rc_buf_destroy(&game->buffer);
rc_buffer_destroy(&game->buffer);
free(game);
}
@ -780,6 +852,8 @@ static void rc_client_load_error(rc_client_load_state_t* load_state, int result,
rc_mutex_unlock(&load_state->client->state.mutex);
RC_CLIENT_LOG_ERR_FORMATTED(load_state->client, "Load failed (%d): %s", result, error_message);
if (load_state->callback)
load_state->callback(result, error_message, load_state->client, load_state->callback_userdata);
@ -815,6 +889,10 @@ static void rc_client_invalidate_memref_achievements(rc_client_game_info_t* game
if (rc_trigger_contains_memref(achievement->trigger, memref)) {
achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_DISABLED;
achievement->public_.bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED;
if (achievement->trigger)
achievement->trigger->state = RC_TRIGGER_STATE_DISABLED;
RC_CLIENT_LOG_WARN_FORMATTED(client, "Disabled achievement %u. Invalid address %06X", achievement->public_.id, memref->address);
}
}
@ -842,6 +920,9 @@ static void rc_client_invalidate_memref_leaderboards(rc_client_game_info_t* game
else
continue;
if (leaderboard->lboard)
leaderboard->lboard->state = RC_LBOARD_STATE_DISABLED;
RC_CLIENT_LOG_WARN_FORMATTED(client, "Disabled leaderboard %u. Invalid address %06X", leaderboard->public_.id, memref->address);
}
}
@ -889,33 +970,33 @@ static void rc_client_update_legacy_runtime_achievements(rc_client_game_info_t*
rc_client_achievement_info_t* achievement;
rc_client_achievement_info_t* stop;
rc_runtime_trigger_t* trigger;
rc_client_subset_info_t* subset;
rc_client_subset_info_t* subset = game->subsets;
for (; subset; subset = subset->next) {
if (active_count <= game->runtime.trigger_capacity) {
if (active_count != 0)
memset(game->runtime.triggers, 0, active_count * sizeof(rc_runtime_trigger_t));
} else {
if (game->runtime.triggers)
free(game->runtime.triggers);
game->runtime.trigger_capacity = active_count;
game->runtime.triggers = (rc_runtime_trigger_t*)calloc(1, active_count * sizeof(rc_runtime_trigger_t));
}
trigger = game->runtime.triggers;
if (!trigger) {
/* malloc failed, no way to report error, just bail */
game->runtime.trigger_count = 0;
return;
}
for (subset = game->subsets; subset; subset = subset->next) {
if (!subset->active)
continue;
achievement = subset->achievements;
stop = achievement + subset->public_.num_achievements;
if (active_count <= game->runtime.trigger_capacity) {
if (active_count != 0)
memset(game->runtime.triggers, 0, active_count * sizeof(rc_runtime_trigger_t));
}
else {
if (game->runtime.triggers)
free(game->runtime.triggers);
game->runtime.trigger_capacity = active_count;
game->runtime.triggers = (rc_runtime_trigger_t*)calloc(1, active_count * sizeof(rc_runtime_trigger_t));
if (!game->runtime.triggers) {
/* Unexpected, no callback available, just fail */
break;
}
}
trigger = game->runtime.triggers;
achievement = subset->achievements;
for (; achievement < stop; ++achievement) {
if (achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE) {
trigger->id = achievement->public_.id;
@ -944,7 +1025,7 @@ static uint32_t rc_client_subset_count_active_achievements(const rc_client_subse
return active_count;
}
static void rc_client_update_active_achievements(rc_client_game_info_t* game)
void rc_client_update_active_achievements(rc_client_game_info_t* game)
{
uint32_t active_count = 0;
rc_client_subset_info_t* subset = game->subsets;
@ -997,6 +1078,9 @@ static uint32_t rc_client_subset_toggle_hardcore_achievements(rc_client_subset_i
client_event.achievement = &achievement->public_;
client->callbacks.event_handler(&client_event, client);
}
if (achievement->trigger && rc_trigger_state_active(achievement->trigger->state))
achievement->trigger->state = RC_TRIGGER_STATE_TRIGGERED;
}
}
@ -1024,12 +1108,89 @@ static void rc_client_activate_achievements(rc_client_game_info_t* game, rc_clie
rc_client_toggle_hardcore_achievements(game, client, active_bit);
}
static void rc_client_update_legacy_runtime_leaderboards(rc_client_game_info_t* game, uint32_t active_count)
{
if (active_count > 0) {
rc_client_leaderboard_info_t* leaderboard;
rc_client_leaderboard_info_t* stop;
rc_client_subset_info_t* subset;
rc_runtime_lboard_t* lboard;
if (active_count <= game->runtime.lboard_capacity) {
if (active_count != 0)
memset(game->runtime.lboards, 0, active_count * sizeof(rc_runtime_lboard_t));
} else {
if (game->runtime.lboards)
free(game->runtime.lboards);
game->runtime.lboard_capacity = active_count;
game->runtime.lboards = (rc_runtime_lboard_t*)calloc(1, active_count * sizeof(rc_runtime_lboard_t));
}
lboard = game->runtime.lboards;
if (!lboard) {
/* malloc failed. no way to report error, just bail */
game->runtime.lboard_count = 0;
return;
}
for (subset = game->subsets; subset; subset = subset->next) {
if (!subset->active)
continue;
leaderboard = subset->leaderboards;
stop = leaderboard + subset->public_.num_leaderboards;
for (; leaderboard < stop; ++leaderboard) {
if (leaderboard->public_.state == RC_CLIENT_LEADERBOARD_STATE_ACTIVE ||
leaderboard->public_.state == RC_CLIENT_LEADERBOARD_STATE_TRACKING) {
lboard->id = leaderboard->public_.id;
memcpy(lboard->md5, leaderboard->md5, 16);
lboard->lboard = leaderboard->lboard;
++lboard;
}
}
}
}
game->runtime.lboard_count = active_count;
}
void rc_client_update_active_leaderboards(rc_client_game_info_t* game)
{
rc_client_leaderboard_info_t* leaderboard;
rc_client_leaderboard_info_t* stop;
uint32_t active_count = 0;
rc_client_subset_info_t* subset = game->subsets;
for (; subset; subset = subset->next)
{
if (!subset->active)
continue;
leaderboard = subset->leaderboards;
stop = leaderboard + subset->public_.num_leaderboards;
for (; leaderboard < stop; ++leaderboard)
{
switch (leaderboard->public_.state)
{
case RC_CLIENT_LEADERBOARD_STATE_ACTIVE:
case RC_CLIENT_LEADERBOARD_STATE_TRACKING:
++active_count;
break;
}
}
}
rc_client_update_legacy_runtime_leaderboards(game, active_count);
}
static void rc_client_activate_leaderboards(rc_client_game_info_t* game, rc_client_t* client)
{
rc_client_leaderboard_info_t* leaderboard;
rc_client_leaderboard_info_t* stop;
unsigned active_count = 0;
uint32_t active_count = 0;
rc_client_subset_info_t* subset = game->subsets;
for (; subset; subset = subset->next) {
if (!subset->active)
@ -1061,43 +1222,7 @@ static void rc_client_activate_leaderboards(rc_client_game_info_t* game, rc_clie
}
}
if (active_count > 0) {
rc_runtime_lboard_t* lboard;
if (active_count <= game->runtime.lboard_capacity) {
if (active_count != 0)
memset(game->runtime.lboards, 0, active_count * sizeof(rc_runtime_lboard_t));
}
else {
if (game->runtime.lboards)
free(game->runtime.lboards);
game->runtime.lboard_capacity = active_count;
game->runtime.lboards = (rc_runtime_lboard_t*)calloc(1, active_count * sizeof(rc_runtime_lboard_t));
}
lboard = game->runtime.lboards;
subset = game->subsets;
for (; subset; subset = subset->next) {
if (!subset->active)
continue;
leaderboard = subset->leaderboards;
stop = leaderboard + subset->public_.num_leaderboards;
for (; leaderboard < stop; ++leaderboard) {
if (leaderboard->public_.state == RC_CLIENT_LEADERBOARD_STATE_ACTIVE ||
leaderboard->public_.state == RC_CLIENT_LEADERBOARD_STATE_TRACKING) {
lboard->id = leaderboard->public_.id;
memcpy(lboard->md5, leaderboard->md5, 16);
lboard->lboard = leaderboard->lboard;
++lboard;
}
}
}
}
game->runtime.lboard_count = active_count;
rc_client_update_legacy_runtime_leaderboards(game, active_count);
}
static void rc_client_deactivate_leaderboards(rc_client_game_info_t* game, rc_client_t* client)
@ -1225,7 +1350,7 @@ static void rc_client_activate_game(rc_client_load_state_t* load_state, rc_api_s
if (load_state->hash->hash[0] != '[') {
if (load_state->client->state.spectator_mode != RC_CLIENT_SPECTATOR_MODE_LOCKED) {
/* schedule the periodic ping */
rc_client_scheduled_callback_data_t* callback_data = rc_buf_alloc(&load_state->game->buffer, sizeof(rc_client_scheduled_callback_data_t));
rc_client_scheduled_callback_data_t* callback_data = rc_buffer_alloc(&load_state->game->buffer, sizeof(rc_client_scheduled_callback_data_t));
memset(callback_data, 0, sizeof(*callback_data));
callback_data->callback = rc_client_ping;
callback_data->related_id = load_state->game->public_.id;
@ -1260,10 +1385,15 @@ static void rc_client_start_session_callback(const rc_api_server_response_t* ser
const char* error_message;
int result;
if (rc_client_async_handle_aborted(load_state->client, &load_state->async_handle)) {
rc_client_t* client = load_state->client;
rc_client_load_aborted(load_state);
RC_CLIENT_LOG_VERBOSE(client, "Load aborted while starting session");
result = rc_client_end_async(load_state->client, &load_state->async_handle);
if (result) {
if (result != RC_CLIENT_ASYNC_DESTROYED) {
rc_client_t* client = load_state->client;
rc_client_load_aborted(load_state);
RC_CLIENT_LOG_VERBOSE(client, "Load aborted while starting session");
} else {
rc_client_free_load_state(load_state);
}
return;
}
@ -1315,6 +1445,7 @@ static void rc_client_begin_start_session(rc_client_load_state_t* load_state)
else {
rc_client_begin_load_state(load_state, RC_CLIENT_LOAD_STATE_STARTING_SESSION, 1);
RC_CLIENT_LOG_VERBOSE_FORMATTED(client, "Starting session for game %u", start_session_params.game_id);
rc_client_begin_async(client, &load_state->async_handle);
client->callbacks.server_call(&start_session_request, rc_client_start_session_callback, load_state, client);
rc_api_destroy_request(&start_session_request);
}
@ -1329,7 +1460,7 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
rc_client_achievement_info_t* achievements;
rc_client_achievement_info_t* achievement;
rc_client_achievement_info_t* scan;
rc_api_buffer_t* buffer;
rc_buffer_t* buffer;
rc_parse_state_t parse;
const char* memaddr;
size_t size;
@ -1362,12 +1493,12 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
+ sizeof(rc_trigger_t) + sizeof(rc_condset_t) * 2 /* trigger container */
+ sizeof(rc_condition_t) * 8 /* assume average trigger length of 8 conditions */
+ sizeof(rc_client_achievement_info_t);
rc_buf_reserve(&load_state->game->buffer, size * num_achievements);
rc_buffer_reserve(&load_state->game->buffer, size * num_achievements);
/* allocate the achievement array */
size = sizeof(rc_client_achievement_info_t) * num_achievements;
buffer = &load_state->game->buffer;
achievement = achievements = rc_buf_alloc(buffer, size);
achievement = achievements = rc_buffer_alloc(buffer, size);
memset(achievements, 0, size);
/* copy the achievement data */
@ -1375,8 +1506,8 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
if (read->category != RC_ACHIEVEMENT_CATEGORY_CORE && !load_state->client->state.unofficial_enabled)
continue;
achievement->public_.title = rc_buf_strcpy(buffer, read->title);
achievement->public_.description = rc_buf_strcpy(buffer, read->description);
achievement->public_.title = rc_buffer_strcpy(buffer, read->title);
achievement->public_.description = rc_buffer_strcpy(buffer, read->description);
snprintf(achievement->public_.badge_name, sizeof(achievement->public_.badge_name), "%s", read->badge_name);
achievement->public_.id = read->id;
achievement->public_.points = read->points;
@ -1394,7 +1525,7 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
}
else {
/* populate the item, using the communal memrefs pool */
rc_init_parse_state(&parse, rc_buf_reserve(buffer, trigger_size), NULL, 0);
rc_init_parse_state(&parse, rc_buffer_reserve(buffer, trigger_size), NULL, 0);
parse.first_memref = &load_state->game->runtime.memrefs;
parse.variables = &load_state->game->runtime.variables;
achievement->trigger = RC_ALLOC(rc_trigger_t, &parse);
@ -1406,7 +1537,7 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
achievement->public_.bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED;
}
else {
rc_buf_consume(buffer, parse.buffer, (char*)parse.buffer + parse.offset);
rc_buffer_consume(buffer, parse.buffer, (uint8_t*)parse.buffer + parse.offset);
achievement->trigger->memrefs = NULL; /* memrefs managed by runtime */
}
@ -1425,7 +1556,7 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
}
}
if (!achievement->author)
achievement->author = rc_buf_strcpy(buffer, read->author);
achievement->author = rc_buffer_strcpy(buffer, read->author);
++achievement;
}
@ -1433,9 +1564,9 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
subset->achievements = achievements;
}
static uint8_t rc_client_map_leaderboard_format(const rc_api_leaderboard_definition_t* defn)
uint8_t rc_client_map_leaderboard_format(int format)
{
switch (defn->format) {
switch (format) {
case RC_FORMAT_SECONDS:
case RC_FORMAT_CENTISECS:
case RC_FORMAT_MINUTES:
@ -1466,7 +1597,7 @@ static void rc_client_copy_leaderboards(rc_client_load_state_t* load_state,
const rc_api_leaderboard_definition_t* stop;
rc_client_leaderboard_info_t* leaderboards;
rc_client_leaderboard_info_t* leaderboard;
rc_api_buffer_t* buffer;
rc_buffer_t* buffer;
rc_parse_state_t parse;
const char* memaddr;
const char* ptr;
@ -1487,22 +1618,22 @@ static void rc_client_copy_leaderboards(rc_client_load_state_t* load_state,
+ (sizeof(rc_value_t) + sizeof(rc_condset_t)) /* value */
+ sizeof(rc_condition_t) * 4 * 4 /* assume average of 4 conditions in each start/submit/cancel/value */
+ sizeof(rc_client_leaderboard_info_t);
rc_buf_reserve(&load_state->game->buffer, size * num_leaderboards);
rc_buffer_reserve(&load_state->game->buffer, size * num_leaderboards);
/* allocate the achievement array */
size = sizeof(rc_client_leaderboard_info_t) * num_leaderboards;
buffer = &load_state->game->buffer;
leaderboard = leaderboards = rc_buf_alloc(buffer, size);
leaderboard = leaderboards = rc_buffer_alloc(buffer, size);
memset(leaderboards, 0, size);
/* copy the achievement data */
read = leaderboard_definitions;
stop = read + num_leaderboards;
do {
leaderboard->public_.title = rc_buf_strcpy(buffer, read->title);
leaderboard->public_.description = rc_buf_strcpy(buffer, read->description);
leaderboard->public_.title = rc_buffer_strcpy(buffer, read->title);
leaderboard->public_.description = rc_buffer_strcpy(buffer, read->description);
leaderboard->public_.id = read->id;
leaderboard->public_.format = rc_client_map_leaderboard_format(read);
leaderboard->public_.format = rc_client_map_leaderboard_format(read->format);
leaderboard->public_.lower_is_better = read->lower_is_better;
leaderboard->format = (uint8_t)read->format;
leaderboard->hidden = (uint8_t)read->hidden;
@ -1527,7 +1658,7 @@ static void rc_client_copy_leaderboards(rc_client_load_state_t* load_state,
}
else {
/* populate the item, using the communal memrefs pool */
rc_init_parse_state(&parse, rc_buf_reserve(buffer, lboard_size), NULL, 0);
rc_init_parse_state(&parse, rc_buffer_reserve(buffer, lboard_size), NULL, 0);
parse.first_memref = &load_state->game->runtime.memrefs;
parse.variables = &load_state->game->runtime.variables;
leaderboard->lboard = RC_ALLOC(rc_lboard_t, &parse);
@ -1538,7 +1669,7 @@ static void rc_client_copy_leaderboards(rc_client_load_state_t* load_state,
leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_DISABLED;
}
else {
rc_buf_consume(buffer, parse.buffer, (char*)parse.buffer + parse.offset);
rc_buffer_consume(buffer, parse.buffer, (uint8_t*)parse.buffer + parse.offset);
leaderboard->lboard->memrefs = NULL; /* memrefs managed by runtime */
}
@ -1559,7 +1690,7 @@ static const char* rc_client_subset_extract_title(rc_client_game_info_t* game, c
const char* start = subset_prefix + 10;
const char* stop = strstr(start, "]");
const size_t len = stop - start;
char* result = (char*)rc_buf_alloc(&game->buffer, len + 1);
char* result = (char*)rc_buffer_alloc(&game->buffer, len + 1);
memcpy(result, start, len);
result[len] = '\0';
@ -1577,10 +1708,15 @@ static void rc_client_fetch_game_data_callback(const rc_api_server_response_t* s
const char* error_message;
int result;
if (rc_client_async_handle_aborted(load_state->client, &load_state->async_handle)) {
rc_client_t* client = load_state->client;
rc_client_load_aborted(load_state);
RC_CLIENT_LOG_VERBOSE(client, "Load aborted while fetching game data");
result = rc_client_end_async(load_state->client, &load_state->async_handle);
if (result) {
if (result != RC_CLIENT_ASYNC_DESTROYED) {
rc_client_t* client = load_state->client;
rc_client_load_aborted(load_state);
RC_CLIENT_LOG_VERBOSE(client, "Load aborted while fetching game data");
} else {
rc_client_free_load_state(load_state);
}
return;
}
@ -1598,7 +1734,7 @@ static void rc_client_fetch_game_data_callback(const rc_api_server_response_t* s
else {
rc_client_subset_info_t* subset;
subset = (rc_client_subset_info_t*)rc_buf_alloc(&load_state->game->buffer, sizeof(rc_client_subset_info_t));
subset = (rc_client_subset_info_t*)rc_buffer_alloc(&load_state->game->buffer, sizeof(rc_client_subset_info_t));
memset(subset, 0, sizeof(*subset));
subset->public_.id = fetch_game_data_response.id;
subset->active = 1;
@ -1630,7 +1766,7 @@ static void rc_client_fetch_game_data_callback(const rc_api_server_response_t* s
if (!load_state->game->subsets) {
/* core set */
rc_mutex_lock(&load_state->client->state.mutex);
load_state->game->public_.title = rc_buf_strcpy(&load_state->game->buffer, fetch_game_data_response.title);
load_state->game->public_.title = rc_buffer_strcpy(&load_state->game->buffer, fetch_game_data_response.title);
load_state->game->subsets = subset;
load_state->game->public_.badge_name = subset->public_.badge_name;
load_state->game->public_.console_id = fetch_game_data_response.console_id;
@ -1662,7 +1798,7 @@ static void rc_client_fetch_game_data_callback(const rc_api_server_response_t* s
}
}
subset->public_.title = rc_buf_strcpy(&load_state->game->buffer, fetch_game_data_response.title);
subset->public_.title = rc_buffer_strcpy(&load_state->game->buffer, fetch_game_data_response.title);
}
/* append to subset list */
@ -1723,7 +1859,7 @@ static void rc_client_begin_fetch_game_data(rc_client_load_state_t* load_state)
count++;
}
ptr = (char*)rc_buf_alloc(&load_state->game->buffer, size);
ptr = (char*)rc_buffer_alloc(&load_state->game->buffer, size);
ptr += size - 1;
*ptr = '\0';
game_hash = load_state->game->media_hash->game_hash;
@ -1798,7 +1934,9 @@ static void rc_client_begin_fetch_game_data(rc_client_load_state_t* load_state)
rc_client_begin_load_state(load_state, RC_CLIENT_LOAD_STATE_FETCHING_GAME_DATA, 1);
RC_CLIENT_LOG_VERBOSE_FORMATTED(client, "Fetching data for game %u", fetch_game_data_request.game_id);
rc_client_begin_async(client, &load_state->async_handle);
client->callbacks.server_call(&request, rc_client_fetch_game_data_callback, load_state, client);
rc_api_destroy_request(&request);
}
@ -1811,9 +1949,14 @@ static void rc_client_identify_game_callback(const rc_api_server_response_t* ser
const char* error_message;
int result;
if (rc_client_async_handle_aborted(client, &load_state->async_handle)) {
rc_client_load_aborted(load_state);
RC_CLIENT_LOG_VERBOSE(client, "Load aborted during game identification");
result = rc_client_end_async(client, &load_state->async_handle);
if (result) {
if (result != RC_CLIENT_ASYNC_DESTROYED) {
rc_client_load_aborted(load_state);
RC_CLIENT_LOG_VERBOSE(client, "Load aborted during game identification");
} else {
rc_client_free_load_state(load_state);
}
return;
}
@ -1856,7 +1999,7 @@ rc_client_game_hash_t* rc_client_find_game_hash(rc_client_t* client, const char*
}
if (!game_hash) {
game_hash = rc_buf_alloc(&client->state.buffer, sizeof(rc_client_game_hash_t));
game_hash = rc_buffer_alloc(&client->state.buffer, sizeof(rc_client_game_hash_t));
memset(game_hash, 0, sizeof(*game_hash));
snprintf(game_hash->hash, sizeof(game_hash->hash), "%s", hash);
game_hash->game_id = RC_CLIENT_UNKNOWN_GAME_ID;
@ -1888,7 +2031,7 @@ static rc_client_async_handle_t* rc_client_load_game(rc_client_load_state_t* loa
return NULL;
}
rc_buf_init(&load_state->game->buffer);
rc_buffer_init(&load_state->game->buffer);
rc_runtime_init(&load_state->game->runtime);
}
}
@ -1906,7 +2049,7 @@ static rc_client_async_handle_t* rc_client_load_game(rc_client_load_state_t* loa
if (file_path) {
rc_client_media_hash_t* media_hash =
(rc_client_media_hash_t*)rc_buf_alloc(&load_state->game->buffer, sizeof(*media_hash));
(rc_client_media_hash_t*)rc_buffer_alloc(&load_state->game->buffer, sizeof(*media_hash));
media_hash->game_hash = load_state->hash;
media_hash->path_djb2 = rc_djb2(file_path);
media_hash->next = load_state->game->media_hash;
@ -1932,6 +2075,7 @@ static rc_client_async_handle_t* rc_client_load_game(rc_client_load_state_t* loa
rc_client_begin_load_state(load_state, RC_CLIENT_LOAD_STATE_IDENTIFYING_GAME, 1);
rc_client_begin_async(client, &load_state->async_handle);
client->callbacks.server_call(&request, rc_client_identify_game_callback, load_state, client);
rc_api_destroy_request(&request);
@ -2101,7 +2245,12 @@ void rc_client_unload_game(rc_client_t* client)
game = client->game;
client->game = NULL;
client->state.load = NULL;
if (client->state.load) {
/* this mimics rc_client_abort_async without nesting the lock */
client->state.load->async_handle.aborted = RC_CLIENT_ASYNC_ABORTED;
client->state.load = NULL;
}
if (client->state.spectator_mode == RC_CLIENT_SPECTATOR_MODE_LOCKED)
client->state.spectator_mode = RC_CLIENT_SPECTATOR_MODE_ON;
@ -2162,11 +2311,14 @@ static void rc_client_identify_changed_media_callback(const rc_api_server_respon
int result = rc_api_process_resolve_hash_server_response(&resolve_hash_response, server_response);
const char* error_message = rc_client_server_error_message(&result, server_response->http_status_code, &resolve_hash_response.response);
if (rc_client_async_handle_aborted(client, &load_state->async_handle)) {
RC_CLIENT_LOG_VERBOSE(client, "Media change aborted");
/* if lookup succeeded, still capture the new hash */
if (result == RC_OK)
load_state->hash->game_id = resolve_hash_response.game_id;
const int async_aborted = rc_client_end_async(client, &load_state->async_handle);
if (async_aborted) {
if (async_aborted != RC_CLIENT_ASYNC_DESTROYED) {
RC_CLIENT_LOG_VERBOSE(client, "Media change aborted");
/* if lookup succeeded, still capture the new hash */
if (result == RC_OK)
load_state->hash->game_id = resolve_hash_response.game_id;
}
}
else if (client->game != load_state->game) {
/* loaded game changed. return success regardless of result */
@ -2301,7 +2453,7 @@ rc_client_async_handle_t* rc_client_begin_change_media(rc_client_t* client, cons
game_hash = rc_client_find_game_hash(client, hash);
media_hash = (rc_client_media_hash_t*)rc_buf_alloc(&game->buffer, sizeof(*media_hash));
media_hash = (rc_client_media_hash_t*)rc_buffer_alloc(&game->buffer, sizeof(*media_hash));
media_hash->game_hash = game_hash;
media_hash->path_djb2 = path_djb2;
@ -2348,6 +2500,7 @@ rc_client_async_handle_t* rc_client_begin_change_media(rc_client_t* client, cons
callback_data->hash = game_hash;
callback_data->game = game;
rc_client_begin_async(client, &callback_data->async_handle);
client->callbacks.server_call(&request, rc_client_identify_changed_media_callback, callback_data, client);
rc_api_destroy_request(&request);
@ -2515,7 +2668,7 @@ static const char* rc_client_get_subset_achievement_bucket_label(uint8_t bucket_
label = rc_client_get_achievement_bucket_label(bucket_type);
new_label_len = strlen(subset->public_.title) + strlen(label) + 4;
new_label = (char*)rc_buf_alloc(&game->buffer, new_label_len);
new_label = (char*)rc_buffer_alloc(&game->buffer, new_label_len);
snprintf(new_label, new_label_len, "%s - %s", subset->public_.title, label);
*ptr = new_label;
@ -2856,7 +3009,7 @@ static void rc_client_award_achievement_callback(const rc_api_server_response_t*
if (award_achievement_response.response.error_message && !rc_client_should_retry(server_response)) {
/* actual error from server */
RC_CLIENT_LOG_ERR_FORMATTED(ach_data->client, "Error awarding achievement %u: %s", ach_data->id, error_message);
rc_client_raise_server_error_event(ach_data->client, "award_achievement", award_achievement_response.response.error_message);
rc_client_raise_server_error_event(ach_data->client, "award_achievement", ach_data->id, result, award_achievement_response.response.error_message);
}
else if (ach_data->retry_count++ == 0) {
/* first retry is immediate */
@ -2874,7 +3027,7 @@ static void rc_client_award_achievement_callback(const rc_api_server_response_t*
ach_data->scheduled_callback_data = (rc_client_scheduled_callback_data_t*)calloc(1, sizeof(*ach_data->scheduled_callback_data));
if (!ach_data->scheduled_callback_data) {
RC_CLIENT_LOG_ERR_FORMATTED(ach_data->client, "Failed to allocate scheduled callback data for reattempt to unlock achievement %u", ach_data->id);
rc_client_raise_server_error_event(ach_data->client, "award_achievement", rc_error_str(RC_OUT_OF_MEMORY));
rc_client_raise_server_error_event(ach_data->client, "award_achievement", ach_data->id, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY));
return;
}
ach_data->scheduled_callback_data->callback = rc_client_award_achievement_retry;
@ -3018,7 +3171,7 @@ static void rc_client_award_achievement(rc_client_t* client, rc_client_achieveme
callback_data = (rc_client_award_achievement_callback_data_t*)calloc(1, sizeof(*callback_data));
if (!callback_data) {
RC_CLIENT_LOG_ERR_FORMATTED(client, "Failed to allocate callback data for unlocking achievement %u", achievement->public_.id);
rc_client_raise_server_error_event(client, "award_achievement", rc_error_str(RC_OUT_OF_MEMORY));
rc_client_raise_server_error_event(client, "award_achievement", achievement->public_.id, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY));
return;
}
callback_data->client = client;
@ -3118,7 +3271,7 @@ static const char* rc_client_get_subset_leaderboard_bucket_label(uint8_t bucket_
label = rc_client_get_leaderboard_bucket_label(bucket_type);
new_label_len = strlen(subset->public_.title) + strlen(label) + 4;
new_label = (char*)rc_buf_alloc(&game->buffer, new_label_len);
new_label = (char*)rc_buffer_alloc(&game->buffer, new_label_len);
snprintf(new_label, new_label_len, "%s - %s", subset->public_.title, label);
*ptr = new_label;
@ -3379,7 +3532,7 @@ static void rc_client_allocate_leaderboard_tracker(rc_client_game_info_t* game,
if (!available_tracker) {
rc_client_leaderboard_tracker_info_t** next = &game->leaderboard_trackers;
available_tracker = (rc_client_leaderboard_tracker_info_t*)rc_buf_alloc(&game->buffer, sizeof(*available_tracker));
available_tracker = (rc_client_leaderboard_tracker_info_t*)rc_buffer_alloc(&game->buffer, sizeof(*available_tracker));
memset(available_tracker, 0, sizeof(*available_tracker));
available_tracker->public_.id = 1;
@ -3401,7 +3554,7 @@ static void rc_client_allocate_leaderboard_tracker(rc_client_game_info_t* game,
game->pending_events |= RC_CLIENT_GAME_PENDING_EVENT_LEADERBOARD_TRACKER;
}
static void rc_client_release_leaderboard_tracker(rc_client_game_info_t* game, rc_client_leaderboard_info_t* leaderboard)
void rc_client_release_leaderboard_tracker(rc_client_game_info_t* game, rc_client_leaderboard_info_t* leaderboard)
{
rc_client_leaderboard_tracker_info_t* tracker = leaderboard->tracker;
leaderboard->tracker = NULL;
@ -3476,7 +3629,7 @@ static void rc_client_raise_scoreboard_event(rc_client_submit_leaderboard_entry_
sboard.top_entries = (rc_client_leaderboard_scoreboard_entry_t*)calloc(
response->num_top_entries, sizeof(rc_client_leaderboard_scoreboard_entry_t));
if (sboard.top_entries != NULL) {
unsigned i;
uint32_t i;
for (i = 0; i < response->num_top_entries; i++) {
sboard.top_entries[i].username = response->top_entries[i].username;
sboard.top_entries[i].rank = response->top_entries[i].rank;
@ -3511,7 +3664,7 @@ static void rc_client_submit_leaderboard_entry_callback(const rc_api_server_resp
if (submit_lboard_entry_response.response.error_message && !rc_client_should_retry(server_response)) {
/* actual error from server */
RC_CLIENT_LOG_ERR_FORMATTED(lboard_data->client, "Error submitting leaderboard entry %u: %s", lboard_data->id, error_message);
rc_client_raise_server_error_event(lboard_data->client, "submit_lboard_entry", submit_lboard_entry_response.response.error_message);
rc_client_raise_server_error_event(lboard_data->client, "submit_lboard_entry", lboard_data->id, result, submit_lboard_entry_response.response.error_message);
}
else if (lboard_data->retry_count++ == 0) {
/* first retry is immediate */
@ -3529,7 +3682,7 @@ static void rc_client_submit_leaderboard_entry_callback(const rc_api_server_resp
lboard_data->scheduled_callback_data = (rc_client_scheduled_callback_data_t*)calloc(1, sizeof(*lboard_data->scheduled_callback_data));
if (!lboard_data->scheduled_callback_data) {
RC_CLIENT_LOG_ERR_FORMATTED(lboard_data->client, "Failed to allocate scheduled callback data for reattempt to submit entry for leaderboard %u", lboard_data->id);
rc_client_raise_server_error_event(lboard_data->client, "submit_lboard_entry", rc_error_str(RC_OUT_OF_MEMORY));
rc_client_raise_server_error_event(lboard_data->client, "submit_lboard_entry", lboard_data->id, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY));
return;
}
lboard_data->scheduled_callback_data->callback = rc_client_submit_leaderboard_entry_retry;
@ -3611,7 +3764,7 @@ static void rc_client_submit_leaderboard_entry(rc_client_t* client, rc_client_le
callback_data = (rc_client_submit_leaderboard_entry_callback_data_t*)calloc(1, sizeof(*callback_data));
if (!callback_data) {
RC_CLIENT_LOG_ERR_FORMATTED(client, "Failed to allocate callback data for submitting entry for leaderboard %u", leaderboard->public_.id);
rc_client_raise_server_error_event(client, "submit_lboard_entry", rc_error_str(RC_OUT_OF_MEMORY));
rc_client_raise_server_error_event(client, "submit_lboard_entry", leaderboard->public_.id, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY));
return;
}
callback_data->client = client;
@ -3674,8 +3827,11 @@ static void rc_client_fetch_leaderboard_entries_callback(const rc_api_server_res
const char* error_message;
int result;
if (rc_client_async_handle_aborted(client, &lbinfo_callback_data->async_handle)) {
RC_CLIENT_LOG_VERBOSE(client, "Fetch leaderbord entries aborted");
result = rc_client_end_async(client, &lbinfo_callback_data->async_handle);
if (result) {
if (result != RC_CLIENT_ASYNC_DESTROYED) {
RC_CLIENT_LOG_VERBOSE(client, "Fetch leaderbord entries aborted");
}
free(lbinfo_callback_data);
return;
}
@ -3690,7 +3846,7 @@ static void rc_client_fetch_leaderboard_entries_callback(const rc_api_server_res
rc_client_leaderboard_entry_list_t* list;
const size_t list_size = sizeof(*list) + sizeof(rc_client_leaderboard_entry_t) * lbinfo_response.num_entries;
size_t needed_size = list_size;
unsigned i;
uint32_t i;
for (i = 0; i < lbinfo_response.num_entries; i++)
needed_size += strlen(lbinfo_response.entries[i].username) + 1;
@ -3761,6 +3917,7 @@ static rc_client_async_handle_t* rc_client_begin_fetch_leaderboard_info(rc_clien
callback_data->callback_userdata = callback_userdata;
callback_data->leaderboard_id = lbinfo_request->leaderboard_id;
rc_client_begin_async(client, &callback_data->async_handle);
client->callbacks.server_call(&request, rc_client_fetch_leaderboard_entries_callback, callback_data, client);
rc_api_destroy_request(&request);
@ -3835,8 +3992,15 @@ static void rc_client_ping(rc_client_scheduled_callback_data_t* callback_data, r
char buffer[256];
int result;
rc_runtime_get_richpresence(&client->game->runtime, buffer, sizeof(buffer),
client->state.legacy_peek, client, NULL);
if (!client->callbacks.rich_presence_override ||
!client->callbacks.rich_presence_override(client, buffer, sizeof(buffer))) {
rc_mutex_lock(&client->state.mutex);
rc_runtime_get_richpresence(&client->game->runtime, buffer, sizeof(buffer),
client->state.legacy_peek, client, NULL);
rc_mutex_unlock(&client->state.mutex);
}
memset(&api_params, 0, sizeof(api_params));
api_params.username = client->user.username;
@ -3874,9 +4038,13 @@ size_t rc_client_get_rich_presence_message(rc_client_t* client, char buffer[], s
if (!client || !client->game || !buffer)
return 0;
rc_mutex_lock(&client->state.mutex);
result = rc_runtime_get_richpresence(&client->game->runtime, buffer, (unsigned)buffer_size,
client->state.legacy_peek, client, NULL);
rc_mutex_unlock(&client->state.mutex);
if (result == 0)
result = snprintf(buffer, buffer_size, "Playing %s", client->game->public_.title);
@ -3922,10 +4090,10 @@ static void rc_client_invalidate_processing_memref(rc_client_t* client)
client->state.processing_memref = NULL;
}
static unsigned rc_client_peek_le(unsigned address, unsigned num_bytes, void* ud)
static uint32_t rc_client_peek_le(uint32_t address, uint32_t num_bytes, void* ud)
{
rc_client_t* client = (rc_client_t*)ud;
unsigned value = 0;
uint32_t value = 0;
uint32_t num_read = 0;
/* if we know the address is out of range, and it's part of a pointer chain
@ -3945,7 +4113,7 @@ static unsigned rc_client_peek_le(unsigned address, unsigned num_bytes, void* ud
return 0;
}
static unsigned rc_client_peek(unsigned address, unsigned num_bytes, void* ud)
static uint32_t rc_client_peek(uint32_t address, uint32_t num_bytes, void* ud)
{
rc_client_t* client = (rc_client_t*)ud;
uint8_t buffer[4];
@ -4017,7 +4185,7 @@ int rc_client_is_processing_required(rc_client_t* client)
static void rc_client_update_memref_values(rc_client_t* client)
{
rc_memref_t* memref = client->game->runtime.memrefs;
unsigned value;
uint32_t value;
int invalidated_memref = 0;
for (; memref; memref = memref->next) {
@ -4051,7 +4219,7 @@ static void rc_client_do_frame_process_achievements(rc_client_t* client, rc_clie
for (; achievement < stop; ++achievement) {
rc_trigger_t* trigger = achievement->trigger;
int old_state, new_state;
unsigned old_measured_value;
uint32_t old_measured_value;
if (!trigger || achievement->public_.state != RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE)
continue;
@ -4070,8 +4238,8 @@ static void rc_client_do_frame_process_achievements(rc_client_t* client, rc_clie
if (trigger->measured_as_percent) {
/* if reporting the measured value as a percentage, only show the popup if the percentage changes */
const unsigned old_percent = (unsigned)(((unsigned long long)old_measured_value * 100) / trigger->measured_target);
const unsigned new_percent = (unsigned)(((unsigned long long)trigger->measured_value * 100) / trigger->measured_target);
const uint32_t old_percent = (uint32_t)(((unsigned long long)old_measured_value * 100) / trigger->measured_target);
const uint32_t new_percent = (uint32_t)(((unsigned long long)trigger->measured_value * 100) / trigger->measured_target);
if (old_percent == new_percent)
progress = -1.0;
}
@ -4136,7 +4304,7 @@ static void rc_client_do_frame_update_progress_tracker(rc_client_t* client, rc_c
{
if (!game->progress_tracker.hide_callback) {
game->progress_tracker.hide_callback = (rc_client_scheduled_callback_data_t*)
rc_buf_alloc(&game->buffer, sizeof(rc_client_scheduled_callback_data_t));
rc_buffer_alloc(&game->buffer, sizeof(rc_client_scheduled_callback_data_t));
memset(game->progress_tracker.hide_callback, 0, sizeof(rc_client_scheduled_callback_data_t));
game->progress_tracker.hide_callback->callback = rc_client_progress_tracker_timer_elapsed;
}

View File

@ -11,11 +11,16 @@ extern "C" {
#include "rc_runtime.h"
#include "rc_runtime_types.h"
/*****************************************************************************\
| Callbacks |
\*****************************************************************************/
struct rc_api_fetch_game_data_response_t;
typedef void (*rc_client_post_process_game_data_response_t)(const rc_api_server_response_t* server_response,
struct rc_api_fetch_game_data_response_t* game_data_response, rc_client_t* client, void* userdata);
typedef int (*rc_client_can_submit_achievement_unlock_t)(uint32_t achievement_id, rc_client_t* client);
typedef int (*rc_client_can_submit_leaderboard_entry_t)(uint32_t leaderboard_id, rc_client_t* client);
typedef int (*rc_client_rich_presence_override_t)(rc_client_t* client, char buffer[], size_t buffersize);
typedef struct rc_client_callbacks_t {
rc_client_read_memory_func_t read_memory;
@ -26,6 +31,7 @@ typedef struct rc_client_callbacks_t {
rc_client_post_process_game_data_response_t post_process_game_data_response;
rc_client_can_submit_achievement_unlock_t can_submit_achievement_unlock;
rc_client_can_submit_leaderboard_entry_t can_submit_leaderboard_entry;
rc_client_rich_presence_override_t rich_presence_override;
void* client_data;
} rc_client_callbacks_t;
@ -36,7 +42,7 @@ typedef void (*rc_client_scheduled_callback_t)(struct rc_client_scheduled_callba
typedef struct rc_client_scheduled_callback_data_t
{
rc_clock_t when;
unsigned related_id;
uint32_t related_id;
rc_client_scheduled_callback_t callback;
void* data;
struct rc_client_scheduled_callback_data_t* next;
@ -44,6 +50,10 @@ typedef struct rc_client_scheduled_callback_data_t
void rc_client_schedule_callback(rc_client_t* client, rc_client_scheduled_callback_data_t* scheduled_callback);
/*****************************************************************************\
| Achievements |
\*****************************************************************************/
enum {
RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_NONE = 0,
RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_TRIGGERED = (1 << 1),
@ -83,6 +93,10 @@ typedef struct rc_client_progress_tracker_t {
uint8_t action;
} rc_client_progress_tracker_t;
/*****************************************************************************\
| Leaderboard Trackers |
\*****************************************************************************/
enum {
RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_NONE = 0,
RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_UPDATE = (1 << 1),
@ -93,7 +107,7 @@ enum {
typedef struct rc_client_leaderboard_tracker_info_t {
rc_client_leaderboard_tracker_t public_;
struct rc_client_leaderboard_tracker_info_t* next;
int raw_value;
int32_t raw_value;
uint32_t value_djb2;
@ -103,6 +117,10 @@ typedef struct rc_client_leaderboard_tracker_info_t {
uint8_t value_from_hits;
} rc_client_leaderboard_tracker_info_t;
/*****************************************************************************\
| Leaderboards |
\*****************************************************************************/
enum {
RC_CLIENT_LEADERBOARD_PENDING_EVENT_NONE = 0,
RC_CLIENT_LEADERBOARD_PENDING_EVENT_STARTED = (1 << 1),
@ -119,7 +137,7 @@ typedef struct rc_client_leaderboard_info_t {
rc_client_leaderboard_tracker_info_t* tracker;
uint32_t value_djb2;
int value;
int32_t value;
uint8_t format;
uint8_t pending_events;
@ -127,19 +145,18 @@ typedef struct rc_client_leaderboard_info_t {
uint8_t hidden;
} rc_client_leaderboard_info_t;
uint8_t rc_client_map_leaderboard_format(int format);
/*****************************************************************************\
| Subsets |
\*****************************************************************************/
enum {
RC_CLIENT_SUBSET_PENDING_EVENT_NONE = 0,
RC_CLIENT_SUBSET_PENDING_EVENT_ACHIEVEMENT = (1 << 1),
RC_CLIENT_SUBSET_PENDING_EVENT_LEADERBOARD = (1 << 2)
};
enum {
RC_CLIENT_GAME_PENDING_EVENT_NONE = 0,
RC_CLIENT_GAME_PENDING_EVENT_LEADERBOARD_TRACKER = (1 << 1),
RC_CLIENT_GAME_PENDING_EVENT_UPDATE_ACTIVE_ACHIEVEMENTS = (1 << 2),
RC_CLIENT_GAME_PENDING_EVENT_PROGRESS_TRACKER = (1 << 3)
};
typedef struct rc_client_subset_info_t {
rc_client_subset_t public_;
@ -160,6 +177,12 @@ typedef struct rc_client_subset_info_t {
uint8_t pending_events;
} rc_client_subset_info_t;
void rc_client_begin_load_subset(rc_client_t* client, uint32_t subset_id, rc_client_callback_t callback, void* callback_userdata);
/*****************************************************************************\
| Game |
\*****************************************************************************/
typedef struct rc_client_game_hash_t {
char hash[33];
uint32_t game_id;
@ -174,6 +197,13 @@ typedef struct rc_client_media_hash_t {
uint32_t path_djb2;
} rc_client_media_hash_t;
enum {
RC_CLIENT_GAME_PENDING_EVENT_NONE = 0,
RC_CLIENT_GAME_PENDING_EVENT_LEADERBOARD_TRACKER = (1 << 1),
RC_CLIENT_GAME_PENDING_EVENT_UPDATE_ACTIVE_ACHIEVEMENTS = (1 << 2),
RC_CLIENT_GAME_PENDING_EVENT_PROGRESS_TRACKER = (1 << 3)
};
typedef struct rc_client_game_info_t {
rc_client_game_t public_;
rc_client_leaderboard_tracker_info_t* leaderboard_trackers;
@ -190,17 +220,24 @@ typedef struct rc_client_game_info_t {
uint8_t waiting_for_reset;
uint8_t pending_events;
rc_api_buffer_t buffer;
rc_buffer_t buffer;
} rc_client_game_info_t;
void rc_client_update_active_achievements(rc_client_game_info_t* game);
void rc_client_update_active_leaderboards(rc_client_game_info_t* game);
/*****************************************************************************\
| Client |
\*****************************************************************************/
enum {
RC_CLIENT_LOAD_STATE_NONE,
RC_CLIENT_LOAD_STATE_IDENTIFYING_GAME,
RC_CLIENT_LOAD_STATE_AWAIT_LOGIN,
RC_CLIENT_LOAD_STATE_FETCHING_GAME_DATA,
RC_CLIENT_LOAD_STATE_STARTING_SESSION,
RC_CLIENT_LOAD_STATE_DONE,
RC_CLIENT_LOAD_STATE_UNKNOWN_GAME
RC_CLIENT_LOAD_STATE_NONE,
RC_CLIENT_LOAD_STATE_IDENTIFYING_GAME,
RC_CLIENT_LOAD_STATE_AWAIT_LOGIN,
RC_CLIENT_LOAD_STATE_FETCHING_GAME_DATA,
RC_CLIENT_LOAD_STATE_STARTING_SESSION,
RC_CLIENT_LOAD_STATE_DONE,
RC_CLIENT_LOAD_STATE_UNKNOWN_GAME
};
enum {
@ -232,7 +269,7 @@ struct rc_client_load_state_t;
typedef struct rc_client_state_t {
rc_mutex_t mutex;
rc_api_buffer_t buffer;
rc_buffer_t buffer;
rc_client_scheduled_callback_data_t* scheduled_callbacks;
@ -245,6 +282,7 @@ typedef struct rc_client_state_t {
uint8_t disconnect;
struct rc_client_load_state_t* load;
struct rc_client_async_handle_t* async_handles[4];
rc_memref_t* processing_memref;
rc_peek_t legacy_peek;
@ -261,6 +299,10 @@ struct rc_client_t {
rc_client_state_t state;
};
/*****************************************************************************\
| Helpers |
\*****************************************************************************/
#ifdef RC_NO_VARIADIC_MACROS
void RC_CLIENT_LOG_ERR_FORMATTED(const rc_client_t* client, const char* format, ...);
void RC_CLIENT_LOG_WARN_FORMATTED(const rc_client_t* client, const char* format, ...);
@ -281,7 +323,7 @@ void rc_client_log_message(const rc_client_t* client, const char* message);
#define RC_CLIENT_LOG_VERBOSE(client, message) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_VERBOSE) rc_client_log_message(client, message); }
/* internals pulled from runtime.c */
void rc_runtime_checksum(const char* memaddr, unsigned char* md5);
void rc_runtime_checksum(const char* memaddr, uint8_t* md5);
int rc_trigger_contains_memref(const rc_trigger_t* trigger, const rc_memref_t* memref);
int rc_value_contains_memref(const rc_value_t* value, const rc_memref_t* memref);
/* end runtime.c internals */
@ -299,7 +341,7 @@ enum {
void rc_client_set_legacy_peek(rc_client_t* client, int method);
void rc_client_begin_load_subset(rc_client_t* client, uint32_t subset_id, rc_client_callback_t callback, void* callback_userdata);
void rc_client_release_leaderboard_tracker(rc_client_game_info_t* game, rc_client_leaderboard_info_t* leaderboard);
#ifdef __cplusplus
}

View File

@ -255,7 +255,7 @@ const rc_disallowed_setting_t* rc_libretro_get_disallowed_settings(const char* l
typedef struct rc_disallowed_core_systems_t
{
const char* library_name;
const int disallowed_consoles[4];
const uint32_t disallowed_consoles[4];
} rc_disallowed_core_systems_t;
static const rc_disallowed_core_systems_t rc_disallowed_core_systems[] = {
@ -264,7 +264,7 @@ static const rc_disallowed_core_systems_t rc_disallowed_core_systems[] = {
{ NULL, { 0 } }
};
int rc_libretro_is_system_allowed(const char* library_name, int console_id) {
int rc_libretro_is_system_allowed(const char* library_name, uint32_t console_id) {
const rc_disallowed_core_systems_t* core_filter = rc_disallowed_core_systems;
size_t library_name_length;
size_t i;
@ -288,8 +288,8 @@ int rc_libretro_is_system_allowed(const char* library_name, int console_id) {
return 1;
}
unsigned char* rc_libretro_memory_find_avail(const rc_libretro_memory_regions_t* regions, unsigned address, unsigned* avail) {
unsigned i;
uint8_t* rc_libretro_memory_find_avail(const rc_libretro_memory_regions_t* regions, uint32_t address, uint32_t* avail) {
uint32_t i;
for (i = 0; i < regions->count; ++i) {
const size_t size = regions->size[i];
@ -298,12 +298,12 @@ unsigned char* rc_libretro_memory_find_avail(const rc_libretro_memory_regions_t*
break;
if (avail)
*avail = (unsigned)(size - address);
*avail = (uint32_t)(size - address);
return &regions->data[i][address];
}
address -= (unsigned)size;
address -= (uint32_t)size;
}
if (avail)
@ -312,13 +312,13 @@ unsigned char* rc_libretro_memory_find_avail(const rc_libretro_memory_regions_t*
return NULL;
}
unsigned char* rc_libretro_memory_find(const rc_libretro_memory_regions_t* regions, unsigned address) {
uint8_t* rc_libretro_memory_find(const rc_libretro_memory_regions_t* regions, uint32_t address) {
return rc_libretro_memory_find_avail(regions, address, NULL);
}
uint32_t rc_libretro_memory_read(const rc_libretro_memory_regions_t* regions, unsigned address,
uint32_t rc_libretro_memory_read(const rc_libretro_memory_regions_t* regions, uint32_t address,
uint8_t* buffer, uint32_t num_bytes) {
unsigned i;
uint32_t i;
uint32_t avail;
for (i = 0; i < regions->count; ++i) {
@ -367,7 +367,7 @@ static const char* rc_memory_type_str(int type) {
}
static void rc_libretro_memory_register_region(rc_libretro_memory_regions_t* regions, int type,
unsigned char* data, size_t size, const char* description) {
uint8_t* data, size_t size, const char* description) {
if (size == 0)
return;
@ -419,7 +419,7 @@ static void rc_libretro_memory_init_without_regions(rc_libretro_memory_regions_t
rc_libretro_memory_register_region(regions, RC_MEMORY_TYPE_SAVE_RAM, info.data, info.size, description);
}
static const struct retro_memory_descriptor* rc_libretro_memory_get_descriptor(const struct retro_memory_map* mmap, unsigned real_address, size_t* offset)
static const struct retro_memory_descriptor* rc_libretro_memory_get_descriptor(const struct retro_memory_map* mmap, uint32_t real_address, size_t* offset)
{
const struct retro_memory_descriptor* desc = mmap->descriptors;
const struct retro_memory_descriptor* end = desc + mmap->num_descriptors;
@ -437,14 +437,14 @@ static const struct retro_memory_descriptor* rc_libretro_memory_get_descriptor(c
/* address is in the block if (addr & select) == (start & select) */
if (((desc->start ^ real_address) & desc->select) == 0) {
/* get the relative offset of the address from the start of the memory block */
unsigned reduced_address = real_address - (unsigned)desc->start;
uint32_t reduced_address = real_address - (unsigned)desc->start;
/* remove any bits from the reduced_address that correspond to the bits in the disconnect
* mask and collapse the remaining bits. this code was copied from the mmap_reduce function
* in RetroArch. i'm not exactly sure how it works, but it does. */
unsigned disconnect_mask = (unsigned)desc->disconnect;
uint32_t disconnect_mask = (unsigned)desc->disconnect;
while (disconnect_mask) {
const unsigned tmp = (disconnect_mask - 1) & ~disconnect_mask;
const uint32_t tmp = (disconnect_mask - 1) & ~disconnect_mask;
reduced_address = (reduced_address & tmp) | ((reduced_address >> 1) & ~tmp);
disconnect_mask = (disconnect_mask & (disconnect_mask - 1)) >> 1;
}
@ -466,24 +466,24 @@ static const struct retro_memory_descriptor* rc_libretro_memory_get_descriptor(c
static void rc_libretro_memory_init_from_memory_map(rc_libretro_memory_regions_t* regions, const struct retro_memory_map* mmap,
const rc_memory_regions_t* console_regions) {
char description[64];
unsigned i;
unsigned char* region_start;
unsigned char* desc_start;
uint32_t i;
uint8_t* region_start;
uint8_t* desc_start;
size_t desc_size;
size_t offset;
for (i = 0; i < console_regions->num_regions; ++i) {
const rc_memory_region_t* console_region = &console_regions->region[i];
size_t console_region_size = console_region->end_address - console_region->start_address + 1;
unsigned real_address = console_region->real_address;
unsigned disconnect_size = 0;
uint32_t real_address = console_region->real_address;
uint32_t disconnect_size = 0;
while (console_region_size > 0) {
const struct retro_memory_descriptor* desc = rc_libretro_memory_get_descriptor(mmap, real_address, &offset);
if (!desc) {
if (rc_libretro_verbose_message_callback && console_region->type != RC_MEMORY_TYPE_UNUSED) {
snprintf(description, sizeof(description), "Could not map region starting at $%06X",
real_address - console_region->real_address + console_region->start_address);
(unsigned)(real_address - console_region->real_address + console_region->start_address));
rc_libretro_verbose(description);
}
@ -523,7 +523,7 @@ static void rc_libretro_memory_init_from_memory_map(rc_libretro_memory_regions_t
if (desc_size == 0) {
if (rc_libretro_verbose_message_callback && console_region->type != RC_MEMORY_TYPE_UNUSED) {
snprintf(description, sizeof(description), "Could not map region starting at $%06X",
real_address - console_region->real_address + console_region->start_address);
(unsigned)(real_address - console_region->real_address + console_region->start_address));
rc_libretro_verbose(description);
}
@ -544,7 +544,7 @@ static void rc_libretro_memory_init_from_memory_map(rc_libretro_memory_regions_t
}
}
static unsigned rc_libretro_memory_console_region_to_ram_type(int region_type) {
static uint32_t rc_libretro_memory_console_region_to_ram_type(uint8_t region_type) {
switch (region_type)
{
case RC_MEMORY_TYPE_SAVE_RAM:
@ -561,15 +561,15 @@ static unsigned rc_libretro_memory_console_region_to_ram_type(int region_type) {
static void rc_libretro_memory_init_from_unmapped_memory(rc_libretro_memory_regions_t* regions,
rc_libretro_get_core_memory_info_func get_core_memory_info, const rc_memory_regions_t* console_regions) {
char description[64];
unsigned i, j;
uint32_t i, j;
rc_libretro_core_memory_info_t info;
size_t offset;
for (i = 0; i < console_regions->num_regions; ++i) {
const rc_memory_region_t* console_region = &console_regions->region[i];
const size_t console_region_size = console_region->end_address - console_region->start_address + 1;
const unsigned type = rc_libretro_memory_console_region_to_ram_type(console_region->type);
unsigned base_address = 0;
const uint32_t type = rc_libretro_memory_console_region_to_ram_type(console_region->type);
uint32_t base_address = 0;
for (j = 0; j <= i; ++j) {
const rc_memory_region_t* console_region2 = &console_regions->region[j];
@ -595,7 +595,7 @@ static void rc_libretro_memory_init_from_unmapped_memory(rc_libretro_memory_regi
}
else {
if (rc_libretro_verbose_message_callback && console_region->type != RC_MEMORY_TYPE_UNUSED) {
snprintf(description, sizeof(description), "Could not map region starting at $%06X", console_region->start_address);
snprintf(description, sizeof(description), "Could not map region starting at $%06X", (unsigned)console_region->start_address);
rc_libretro_verbose(description);
}
@ -620,7 +620,7 @@ int rc_libretro_memory_init(rc_libretro_memory_regions_t* regions, const struct
const rc_memory_regions_t* console_regions = rc_console_memory_regions(console_id);
rc_libretro_memory_regions_t new_regions;
int has_valid_region = 0;
unsigned i;
uint32_t i;
if (!regions)
return 0;
@ -676,46 +676,49 @@ void rc_libretro_hash_set_init(struct rc_libretro_hash_set_t* hash_set,
rc_file_seek(file_handle, 0, SEEK_SET);
m3u_contents = (char*)malloc((size_t)file_len + 1);
rc_file_read(file_handle, m3u_contents, (int)file_len);
m3u_contents[file_len] = '\0';
rc_file_close(file_handle);
ptr = m3u_contents;
do
if (m3u_contents)
{
/* ignore whitespace */
while (isspace((int)*ptr))
++ptr;
rc_file_read(file_handle, m3u_contents, (int)file_len);
m3u_contents[file_len] = '\0';
if (*ptr == '#')
rc_file_close(file_handle);
ptr = m3u_contents;
do
{
/* ignore comment unless it's the special SAVEDISK extension */
if (memcmp(ptr, "#SAVEDISK:", 10) == 0)
/* ignore whitespace */
while (isspace((int)*ptr))
++ptr;
if (*ptr == '#')
{
/* get the path to the save disk from the frontend, assign it a bogus hash so
* it doesn't get hashed later */
if (get_image_path(index, image_path, sizeof(image_path)))
/* ignore comment unless it's the special SAVEDISK extension */
if (memcmp(ptr, "#SAVEDISK:", 10) == 0)
{
const char save_disk_hash[33] = "[SAVE DISK]";
rc_libretro_hash_set_add(hash_set, image_path, -1, save_disk_hash);
++index;
/* get the path to the save disk from the frontend, assign it a bogus hash so
* it doesn't get hashed later */
if (get_image_path(index, image_path, sizeof(image_path)))
{
const char save_disk_hash[33] = "[SAVE DISK]";
rc_libretro_hash_set_add(hash_set, image_path, -1, save_disk_hash);
++index;
}
}
}
}
else
{
/* non-empty line, tally a file */
++index;
}
else
{
/* non-empty line, tally a file */
++index;
}
/* find the end of the line */
while (*ptr && *ptr != '\n')
++ptr;
/* find the end of the line */
while (*ptr && *ptr != '\n')
++ptr;
} while (*ptr);
} while (*ptr);
free(m3u_contents);
free(m3u_contents);
}
if (hash_set->entries_count > 0)
{
@ -732,9 +735,9 @@ void rc_libretro_hash_set_destroy(struct rc_libretro_hash_set_t* hash_set) {
memset(hash_set, 0, sizeof(*hash_set));
}
static unsigned rc_libretro_djb2(const char* input)
static uint32_t rc_libretro_djb2(const char* input)
{
unsigned result = 5381;
uint32_t result = 5381;
char c;
while ((c = *input++) != '\0')
@ -744,8 +747,8 @@ static unsigned rc_libretro_djb2(const char* input)
}
void rc_libretro_hash_set_add(struct rc_libretro_hash_set_t* hash_set,
const char* path, int game_id, const char hash[33]) {
const unsigned path_djb2 = (path != NULL) ? rc_libretro_djb2(path) : 0;
const char* path, uint32_t game_id, const char hash[33]) {
const uint32_t path_djb2 = (path != NULL) ? rc_libretro_djb2(path) : 0;
struct rc_libretro_hash_entry_t* entry = NULL;
struct rc_libretro_hash_entry_t* scan;
struct rc_libretro_hash_entry_t* stop = hash_set->entries + hash_set->entries_count;;
@ -790,7 +793,7 @@ void rc_libretro_hash_set_add(struct rc_libretro_hash_set_t* hash_set,
const char* rc_libretro_hash_set_get_hash(const struct rc_libretro_hash_set_t* hash_set, const char* path)
{
const unsigned path_djb2 = rc_libretro_djb2(path);
const uint32_t path_djb2 = rc_libretro_djb2(path);
struct rc_libretro_hash_entry_t* scan = hash_set->entries;
struct rc_libretro_hash_entry_t* stop = scan + hash_set->entries_count;
for (; scan < stop; ++scan)

View File

@ -1,13 +1,16 @@
#ifndef RC_LIBRETRO_H
#define RC_LIBRETRO_H
#ifdef __cplusplus
extern "C" {
#endif
/* this file comes from the libretro repository, which is not an explicit submodule.
* the integration must set up paths appropriately to find it. */
#include <libretro.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
/*****************************************************************************\
| Disallowed Settings |
@ -21,7 +24,7 @@ typedef struct rc_disallowed_setting_t
const rc_disallowed_setting_t* rc_libretro_get_disallowed_settings(const char* library_name);
int rc_libretro_is_setting_allowed(const rc_disallowed_setting_t* disallowed_settings, const char* setting, const char* value);
int rc_libretro_is_system_allowed(const char* library_name, int console_id);
int rc_libretro_is_system_allowed(const char* library_name, uint32_t console_id);
/*****************************************************************************\
| Memory Mapping |
@ -34,27 +37,27 @@ void rc_libretro_init_verbose_message_callback(rc_libretro_message_callback call
#define RC_LIBRETRO_MAX_MEMORY_REGIONS 32
typedef struct rc_libretro_memory_regions_t
{
unsigned char* data[RC_LIBRETRO_MAX_MEMORY_REGIONS];
uint8_t* data[RC_LIBRETRO_MAX_MEMORY_REGIONS];
size_t size[RC_LIBRETRO_MAX_MEMORY_REGIONS];
size_t total_size;
unsigned count;
uint32_t count;
} rc_libretro_memory_regions_t;
typedef struct rc_libretro_core_memory_info_t
{
unsigned char* data;
uint8_t* data;
size_t size;
} rc_libretro_core_memory_info_t;
typedef void (*rc_libretro_get_core_memory_info_func)(unsigned id, rc_libretro_core_memory_info_t* info);
typedef void (*rc_libretro_get_core_memory_info_func)(uint32_t id, rc_libretro_core_memory_info_t* info);
int rc_libretro_memory_init(rc_libretro_memory_regions_t* regions, const struct retro_memory_map* mmap,
rc_libretro_get_core_memory_info_func get_core_memory_info, int console_id);
void rc_libretro_memory_destroy(rc_libretro_memory_regions_t* regions);
unsigned char* rc_libretro_memory_find(const rc_libretro_memory_regions_t* regions, unsigned address);
unsigned char* rc_libretro_memory_find_avail(const rc_libretro_memory_regions_t* regions, unsigned address, unsigned* avail);
uint32_t rc_libretro_memory_read(const rc_libretro_memory_regions_t* regions, unsigned address, uint8_t* buffer, uint32_t num_bytes);
uint8_t* rc_libretro_memory_find(const rc_libretro_memory_regions_t* regions, uint32_t address);
uint8_t* rc_libretro_memory_find_avail(const rc_libretro_memory_regions_t* regions, uint32_t address, uint32_t* avail);
uint32_t rc_libretro_memory_read(const rc_libretro_memory_regions_t* regions, uint32_t address, uint8_t* buffer, uint32_t num_bytes);
/*****************************************************************************\
| Disk Identification |
@ -63,7 +66,7 @@ uint32_t rc_libretro_memory_read(const rc_libretro_memory_regions_t* regions, un
typedef struct rc_libretro_hash_entry_t
{
uint32_t path_djb2;
int game_id;
uint32_t game_id;
char hash[33];
} rc_libretro_hash_entry_t;
@ -74,14 +77,14 @@ typedef struct rc_libretro_hash_set_t
uint16_t entries_size;
} rc_libretro_hash_set_t;
typedef int (*rc_libretro_get_image_path_func)(unsigned index, char* buffer, size_t buffer_size);
typedef int (*rc_libretro_get_image_path_func)(uint32_t index, char* buffer, size_t buffer_size);
void rc_libretro_hash_set_init(struct rc_libretro_hash_set_t* hash_set,
const char* m3u_path, rc_libretro_get_image_path_func get_image_path);
void rc_libretro_hash_set_destroy(struct rc_libretro_hash_set_t* hash_set);
void rc_libretro_hash_set_add(struct rc_libretro_hash_set_t* hash_set,
const char* path, int game_id, const char hash[33]);
const char* path, uint32_t game_id, const char hash[33]);
const char* rc_libretro_hash_set_get_hash(const struct rc_libretro_hash_set_t* hash_set, const char* path);
int rc_libretro_hash_set_get_game_id(const struct rc_libretro_hash_set_t* hash_set, const char* hash);

188
dep/rcheevos/src/rc_util.c Normal file
View File

@ -0,0 +1,188 @@
#include "rc_util.h"
#include "rc_compat.h"
#include "rc_error.h"
#include <stdlib.h>
#include <string.h>
#undef DEBUG_BUFFERS
/* --- rc_buffer --- */
void rc_buffer_init(rc_buffer_t* buffer)
{
buffer->chunk.write = buffer->chunk.start = &buffer->data[0];
buffer->chunk.end = &buffer->data[sizeof(buffer->data)];
buffer->chunk.next = NULL;
/* leave buffer->data uninitialized */
}
void rc_buffer_destroy(rc_buffer_t* buffer)
{
rc_buffer_chunk_t* chunk;
#ifdef DEBUG_BUFFERS
int count = 0;
int wasted = 0;
int total = 0;
#endif
/* first chunk is not allocated. skip it. */
chunk = buffer->chunk.next;
/* deallocate any additional buffers */
while (chunk)
{
rc_buffer_chunk_t* next = chunk->next;
#ifdef DEBUG_BUFFERS
total += (int)(chunk->end - chunk->start);
wasted += (int)(chunk->end - chunk->write);
++count;
#endif
free(chunk);
chunk = next;
}
#ifdef DEBUG_BUFFERS
printf("-- %d allocated buffers (%d/%d used, %d wasted, %0.2f%% efficiency)\n", count,
total - wasted, total, wasted, (float)(100.0 - (wasted * 100.0) / total));
#endif
}
uint8_t* rc_buffer_reserve(rc_buffer_t* buffer, size_t amount)
{
rc_buffer_chunk_t* chunk = &buffer->chunk;
size_t remaining;
while (chunk)
{
remaining = chunk->end - chunk->write;
if (remaining >= amount)
return chunk->write;
if (!chunk->next)
{
/* allocate a chunk of memory that is a multiple of 256-bytes. the first 32 bytes will be associated
* to the chunk header, and the remaining will be used for data.
*/
const size_t chunk_header_size = sizeof(rc_buffer_chunk_t);
const size_t alloc_size = (chunk_header_size + amount + 0xFF) & ~0xFF;
chunk->next = (rc_buffer_chunk_t*)malloc(alloc_size);
if (!chunk->next)
break;
chunk->next->start = (uint8_t*)chunk->next + chunk_header_size;
chunk->next->write = chunk->next->start;
chunk->next->end = (uint8_t*)chunk->next + alloc_size;
chunk->next->next = NULL;
}
chunk = chunk->next;
}
return NULL;
}
void rc_buffer_consume(rc_buffer_t* buffer, const uint8_t* start, uint8_t* end)
{
rc_buffer_chunk_t* chunk = &buffer->chunk;
do
{
if (chunk->write == start)
{
size_t offset = (end - chunk->start);
offset = (offset + 7) & ~7;
chunk->write = &chunk->start[offset];
if (chunk->write > chunk->end)
chunk->write = chunk->end;
break;
}
chunk = chunk->next;
} while (chunk);
}
void* rc_buffer_alloc(rc_buffer_t* buffer, size_t amount)
{
uint8_t* ptr = rc_buffer_reserve(buffer, amount);
rc_buffer_consume(buffer, ptr, ptr + amount);
return (void*)ptr;
}
char* rc_buffer_strncpy(rc_buffer_t* buffer, const char* src, size_t len)
{
uint8_t* dst = rc_buffer_reserve(buffer, len + 1);
memcpy(dst, src, len);
dst[len] = '\0';
rc_buffer_consume(buffer, dst, dst + len + 2);
return (char*)dst;
}
char* rc_buffer_strcpy(rc_buffer_t* buffer, const char* src)
{
return rc_buffer_strncpy(buffer, src, strlen(src));
}
/* --- other --- */
void rc_format_md5(char checksum[33], const uint8_t digest[16])
{
snprintf(checksum, 33, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7],
digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]
);
}
uint32_t rc_djb2(const char* input)
{
uint32_t result = 5381;
char c;
while ((c = *input++) != '\0')
result = ((result << 5) + result) + c; /* result = result * 33 + c */
return result;
}
const char* rc_error_str(int ret)
{
switch (ret) {
case RC_OK: return "OK";
case RC_INVALID_LUA_OPERAND: return "Invalid Lua operand";
case RC_INVALID_MEMORY_OPERAND: return "Invalid memory operand";
case RC_INVALID_CONST_OPERAND: return "Invalid constant operand";
case RC_INVALID_FP_OPERAND: return "Invalid floating-point operand";
case RC_INVALID_CONDITION_TYPE: return "Invalid condition type";
case RC_INVALID_OPERATOR: return "Invalid operator";
case RC_INVALID_REQUIRED_HITS: return "Invalid required hits";
case RC_DUPLICATED_START: return "Duplicated start condition";
case RC_DUPLICATED_CANCEL: return "Duplicated cancel condition";
case RC_DUPLICATED_SUBMIT: return "Duplicated submit condition";
case RC_DUPLICATED_VALUE: return "Duplicated value expression";
case RC_DUPLICATED_PROGRESS: return "Duplicated progress expression";
case RC_MISSING_START: return "Missing start condition";
case RC_MISSING_CANCEL: return "Missing cancel condition";
case RC_MISSING_SUBMIT: return "Missing submit condition";
case RC_MISSING_VALUE: return "Missing value expression";
case RC_INVALID_LBOARD_FIELD: return "Invalid field in leaderboard";
case RC_MISSING_DISPLAY_STRING: return "Missing display string";
case RC_OUT_OF_MEMORY: return "Out of memory";
case RC_INVALID_VALUE_FLAG: return "Invalid flag in value expression";
case RC_MISSING_VALUE_MEASURED: return "Missing measured flag in value expression";
case RC_MULTIPLE_MEASURED: return "Multiple measured targets";
case RC_INVALID_MEASURED_TARGET: return "Invalid measured target";
case RC_INVALID_COMPARISON: return "Invalid comparison";
case RC_INVALID_STATE: return "Invalid state";
case RC_INVALID_JSON: return "Invalid JSON";
case RC_API_FAILURE: return "API call failed";
case RC_LOGIN_REQUIRED: return "Login required";
case RC_NO_GAME_LOADED: return "No game loaded";
case RC_HARDCORE_DISABLED: return "Hardcore disabled";
case RC_ABORTED: return "Aborted";
case RC_NO_RESPONSE: return "No response";
case RC_ACCESS_DENIED: return "Access denied";
case RC_INVALID_CREDENTIALS: return "Invalid credentials";
case RC_EXPIRED_TOKEN: return "Expired token";
default: return "Unknown error";
}
}

View File

@ -0,0 +1,53 @@
#ifndef RC_UTIL_H
#define RC_UTIL_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* A block of memory for variable length data (like strings and arrays).
*/
typedef struct rc_buffer_chunk_t {
/* The current location where data is being written */
uint8_t* write;
/* The first byte past the end of data where writing cannot occur */
uint8_t* end;
/* The first byte of the data */
uint8_t* start;
/* The next block in the allocated memory chain */
struct rc_buffer_chunk_t* next;
}
rc_buffer_chunk_t;
/**
* A preallocated block of memory for variable length data (like strings and arrays).
*/
typedef struct rc_buffer_t {
/* The chunk data (will point at the local data member) */
struct rc_buffer_chunk_t chunk;
/* Small chunk of memory pre-allocated for the chunk */
uint8_t data[256];
}
rc_buffer_t;
void rc_buffer_init(rc_buffer_t* buffer);
void rc_buffer_destroy(rc_buffer_t* buffer);
uint8_t* rc_buffer_reserve(rc_buffer_t* buffer, size_t amount);
void rc_buffer_consume(rc_buffer_t* buffer, const uint8_t* start, uint8_t* end);
void* rc_buffer_alloc(rc_buffer_t* buffer, size_t amount);
char* rc_buffer_strcpy(rc_buffer_t* buffer, const char* src);
char* rc_buffer_strncpy(rc_buffer_t* buffer, const char* src, size_t len);
uint32_t rc_djb2(const char* input);
void rc_format_md5(char checksum[33], const uint8_t digest[16]);
#ifdef __cplusplus
}
#endif
#endif /* RC_UTIL_H */

View File

@ -5,8 +5,8 @@
extern "C" {
#endif
#define RCHEEVOS_VERSION_MAJOR 10
#define RCHEEVOS_VERSION_MINOR 7
#define RCHEEVOS_VERSION_MAJOR 11
#define RCHEEVOS_VERSION_MINOR 0
#define RCHEEVOS_VERSION_PATCH 0
#define RCHEEVOS_MAKE_VERSION(major, minor, patch) (major * 1000000 + minor * 1000 + patch)

View File

@ -3,7 +3,7 @@
#include <stdlib.h>
#include <string.h>
void* rc_alloc_scratch(void* pointer, int* offset, int size, int alignment, rc_scratch_t* scratch, int scratch_object_pointer_offset)
void* rc_alloc_scratch(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset)
{
rc_scratch_buffer_t* buffer;
@ -13,7 +13,7 @@ void* rc_alloc_scratch(void* pointer, int* offset, int size, int alignment, rc_s
/* update how much space will be required in the real buffer */
{
const int aligned_offset = (*offset + alignment - 1) & ~(alignment - 1);
const int32_t aligned_offset = (*offset + alignment - 1) & ~(alignment - 1);
*offset += (aligned_offset - *offset);
*offset += size;
}
@ -21,12 +21,14 @@ void* rc_alloc_scratch(void* pointer, int* offset, int size, int alignment, rc_s
/* find a scratch buffer to hold the temporary data */
buffer = &scratch->buffer;
do {
const int aligned_buffer_offset = (buffer->offset + alignment - 1) & ~(alignment - 1);
const int remaining = sizeof(buffer->buffer) - aligned_buffer_offset;
const uint32_t aligned_buffer_offset = (buffer->offset + alignment - 1) & ~(alignment - 1);
if (aligned_buffer_offset < sizeof(buffer->buffer)) {
const uint32_t remaining = sizeof(buffer->buffer) - aligned_buffer_offset;
if (remaining >= size) {
/* claim the required space from an existing buffer */
return rc_alloc(buffer->buffer, &buffer->offset, size, alignment, NULL, -1);
if (remaining >= size) {
/* claim the required space from an existing buffer */
return rc_alloc(buffer->buffer, &buffer->offset, size, alignment, NULL, -1);
}
}
if (!buffer->next)
@ -36,13 +38,13 @@ void* rc_alloc_scratch(void* pointer, int* offset, int size, int alignment, rc_s
} while (1);
/* not enough space in any existing buffer, allocate more */
if (size > (int)sizeof(buffer->buffer)) {
if (size > (uint32_t)sizeof(buffer->buffer)) {
/* caller is asking for more than we can fit in a standard rc_scratch_buffer_t.
* leverage the fact that the buffer is the last field and extend its size.
* this chunk will be exactly large enough to hold the needed data, and since offset
* will exceed sizeof(buffer->buffer), it will never be eligible to hold anything else.
*/
const int needed = sizeof(rc_scratch_buffer_t) - sizeof(buffer->buffer) + size;
const size_t needed = sizeof(rc_scratch_buffer_t) - sizeof(buffer->buffer) + size;
buffer->next = (rc_scratch_buffer_t*)malloc(needed);
}
else {
@ -62,7 +64,7 @@ void* rc_alloc_scratch(void* pointer, int* offset, int size, int alignment, rc_s
return rc_alloc(buffer->buffer, &buffer->offset, size, alignment, NULL, -1);
}
void* rc_alloc(void* pointer, int* offset, int size, int alignment, rc_scratch_t* scratch, int scratch_object_pointer_offset) {
void* rc_alloc(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset) {
void* ptr;
*offset = (*offset + alignment - 1) & ~(alignment - 1);
@ -76,7 +78,7 @@ void* rc_alloc(void* pointer, int* offset, int size, int alignment, rc_scratch_t
void** scratch_object_pointer = (void**)((char*)&scratch->objs + scratch_object_pointer_offset);
ptr = *scratch_object_pointer;
if (!ptr) {
int used;
int32_t used;
ptr = *scratch_object_pointer = rc_alloc_scratch(NULL, &used, size, alignment, scratch, -1);
}
}
@ -89,8 +91,8 @@ void* rc_alloc(void* pointer, int* offset, int size, int alignment, rc_scratch_t
return ptr;
}
char* rc_alloc_str(rc_parse_state_t* parse, const char* text, int length) {
int used = 0;
char* rc_alloc_str(rc_parse_state_t* parse, const char* text, size_t length) {
int32_t used = 0;
char* ptr;
rc_scratch_string_t** next = &parse->scratch.strings;
@ -109,7 +111,7 @@ char* rc_alloc_str(rc_parse_state_t* parse, const char* text, int length) {
}
*next = (rc_scratch_string_t*)rc_alloc_scratch(NULL, &used, sizeof(rc_scratch_string_t), RC_ALIGNOF(rc_scratch_string_t), &parse->scratch, RC_OFFSETOF(parse->scratch.objs, __rc_scratch_string_t));
ptr = (char*)rc_alloc_scratch(parse->buffer, &parse->offset, length + 1, RC_ALIGNOF(char), &parse->scratch, -1);
ptr = (char*)rc_alloc_scratch(parse->buffer, &parse->offset, (uint32_t)length + 1, RC_ALIGNOF(char), &parse->scratch, -1);
if (!ptr || !*next) {
if (parse->offset >= 0)
@ -158,54 +160,3 @@ void rc_destroy_parse_state(rc_parse_state_t* parse)
buffer = next;
}
}
unsigned rc_djb2(const char* input)
{
unsigned result = 5381;
char c;
while ((c = *input++) != '\0')
result = ((result << 5) + result) + c; /* result = result * 33 + c */
return result;
}
const char* rc_error_str(int ret)
{
switch (ret) {
case RC_OK: return "OK";
case RC_INVALID_LUA_OPERAND: return "Invalid Lua operand";
case RC_INVALID_MEMORY_OPERAND: return "Invalid memory operand";
case RC_INVALID_CONST_OPERAND: return "Invalid constant operand";
case RC_INVALID_FP_OPERAND: return "Invalid floating-point operand";
case RC_INVALID_CONDITION_TYPE: return "Invalid condition type";
case RC_INVALID_OPERATOR: return "Invalid operator";
case RC_INVALID_REQUIRED_HITS: return "Invalid required hits";
case RC_DUPLICATED_START: return "Duplicated start condition";
case RC_DUPLICATED_CANCEL: return "Duplicated cancel condition";
case RC_DUPLICATED_SUBMIT: return "Duplicated submit condition";
case RC_DUPLICATED_VALUE: return "Duplicated value expression";
case RC_DUPLICATED_PROGRESS: return "Duplicated progress expression";
case RC_MISSING_START: return "Missing start condition";
case RC_MISSING_CANCEL: return "Missing cancel condition";
case RC_MISSING_SUBMIT: return "Missing submit condition";
case RC_MISSING_VALUE: return "Missing value expression";
case RC_INVALID_LBOARD_FIELD: return "Invalid field in leaderboard";
case RC_MISSING_DISPLAY_STRING: return "Missing display string";
case RC_OUT_OF_MEMORY: return "Out of memory";
case RC_INVALID_VALUE_FLAG: return "Invalid flag in value expression";
case RC_MISSING_VALUE_MEASURED: return "Missing measured flag in value expression";
case RC_MULTIPLE_MEASURED: return "Multiple measured targets";
case RC_INVALID_MEASURED_TARGET: return "Invalid measured target";
case RC_INVALID_COMPARISON: return "Invalid comparison";
case RC_INVALID_STATE: return "Invalid state";
case RC_INVALID_JSON: return "Invalid JSON";
case RC_API_FAILURE: return "API call failed";
case RC_LOGIN_REQUIRED: return "Login required";
case RC_NO_GAME_LOADED: return "No game loaded";
case RC_HARDCORE_DISABLED: return "Hardcore disabled";
case RC_ABORTED: return "Aborted";
case RC_NO_RESPONSE: return "No response";
default: return "Unknown error";
}
}

View File

@ -3,7 +3,7 @@
#include <stdlib.h>
#include <assert.h>
static int rc_test_condition_compare(unsigned value1, unsigned value2, char oper) {
static int rc_test_condition_compare(uint32_t value1, uint32_t value2, uint8_t oper) {
switch (oper) {
case RC_OPERATOR_EQ: return value1 == value2;
case RC_OPERATOR_NE: return value1 != value2;
@ -149,7 +149,7 @@ static int rc_parse_operator(const char** memaddr) {
}
}
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse, int is_indirect) {
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse, uint8_t is_indirect) {
rc_condition_t* self;
const char* aux;
int result;
@ -323,23 +323,23 @@ int rc_condition_is_combining(const rc_condition_t* self) {
}
static int rc_test_condition_compare_memref_to_const(rc_condition_t* self) {
const unsigned value1 = self->operand1.value.memref->value.value;
const unsigned value2 = self->operand2.value.num;
const uint32_t value1 = self->operand1.value.memref->value.value;
const uint32_t value2 = self->operand2.value.num;
assert(self->operand1.size == self->operand1.value.memref->value.size);
return rc_test_condition_compare(value1, value2, self->oper);
}
static int rc_test_condition_compare_delta_to_const(rc_condition_t* self) {
const rc_memref_value_t* memref1 = &self->operand1.value.memref->value;
const unsigned value1 = (memref1->changed) ? memref1->prior : memref1->value;
const unsigned value2 = self->operand2.value.num;
const uint32_t value1 = (memref1->changed) ? memref1->prior : memref1->value;
const uint32_t value2 = self->operand2.value.num;
assert(self->operand1.size == self->operand1.value.memref->value.size);
return rc_test_condition_compare(value1, value2, self->oper);
}
static int rc_test_condition_compare_memref_to_memref(rc_condition_t* self) {
const unsigned value1 = self->operand1.value.memref->value.value;
const unsigned value2 = self->operand2.value.memref->value.value;
const uint32_t value1 = self->operand1.value.memref->value.value;
const uint32_t value2 = self->operand2.value.memref->value.value;
assert(self->operand1.size == self->operand1.value.memref->value.size);
assert(self->operand2.size == self->operand2.value.memref->value.size);
return rc_test_condition_compare(value1, value2, self->oper);
@ -387,7 +387,7 @@ static int rc_test_condition_compare_delta_to_memref(rc_condition_t* self) {
static int rc_test_condition_compare_memref_to_const_transformed(rc_condition_t* self) {
rc_typed_value_t value1;
const unsigned value2 = self->operand2.value.num;
const uint32_t value2 = self->operand2.value.num;
value1.type = RC_VALUE_TYPE_UNSIGNED;
value1.value.u32 = self->operand1.value.memref->value.value;
@ -399,7 +399,7 @@ static int rc_test_condition_compare_memref_to_const_transformed(rc_condition_t*
static int rc_test_condition_compare_delta_to_const_transformed(rc_condition_t* self) {
rc_typed_value_t value1;
const rc_memref_value_t* memref1 = &self->operand1.value.memref->value;
const unsigned value2 = self->operand2.value.num;
const uint32_t value2 = self->operand2.value.num;
value1.type = RC_VALUE_TYPE_UNSIGNED;
value1.value.u32 = (memref1->changed) ? memref1->prior : memref1->value;

View File

@ -28,7 +28,7 @@ rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse, in
rc_condset_t* self;
rc_condition_t** next;
int in_add_address;
unsigned measured_target = 0;
uint32_t measured_target = 0;
self = RC_ALLOC(rc_condset_t, parse);
self->has_pause = self->is_paused = self->has_indirect_memrefs = 0;
@ -181,7 +181,7 @@ static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, rc
rc_typed_value_t value;
int set_valid, cond_valid, and_next, or_next, reset_next, measured_from_hits, can_measure;
rc_typed_value_t measured_value;
unsigned total_hits;
uint32_t total_hits;
measured_value.type = RC_VALUE_TYPE_NONE;
measured_from_hits = 0;

View File

@ -761,16 +761,19 @@ static const rc_memory_region_t _rc_memory_regions_sg1000[] = {
static const rc_memory_regions_t rc_memory_regions_sg1000 = { _rc_memory_regions_sg1000, 4 };
/* ===== Super Cassette Vision ===== */
/* https://github.com/mamedev/mame/blob/f32bb79e8541ba96d3a8144b220c48fb7536ba4b/src/mame/epoch/scv.cpp#L78-L86 */
/* SCV only has 128 bytes of system RAM, any additional memory is provided on the individual carts and is
* not backed up by battery. */
/* http://www.videogameconsolelibrary.com/pg80-super_cass_vis.htm#page=specs */
static const rc_memory_region_t _rc_memory_regions_scv[] = {
{ 0x000000U, 0x000FFFU, 0x000000U, RC_MEMORY_TYPE_READONLY, "System ROM" },
{ 0x000000U, 0x000FFFU, 0x000000U, RC_MEMORY_TYPE_READONLY, "System ROM" }, /* BIOS */
{ 0x001000U, 0x001FFFU, 0x001000U, RC_MEMORY_TYPE_UNUSED, "" },
{ 0x002000U, 0x003FFFU, 0x002000U, RC_MEMORY_TYPE_VIDEO_RAM, "Video RAM" },
{ 0x002000U, 0x003FFFU, 0x002000U, RC_MEMORY_TYPE_VIDEO_RAM, "Video RAM" }, /* only really goes to $33FF? */
{ 0x004000U, 0x007FFFU, 0x004000U, RC_MEMORY_TYPE_UNUSED, "" },
{ 0x008000U, 0x00DFFFU, 0x008000U, RC_MEMORY_TYPE_READONLY, "Cartridge ROM" },
{ 0x00E000U, 0x00FF7FU, 0x00E000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" },
{ 0x008000U, 0x00FF7FU, 0x008000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Cartridge RAM" },
{ 0x00FF80U, 0x00FFFFU, 0x00FF80U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
};
static const rc_memory_regions_t rc_memory_regions_scv = { _rc_memory_regions_scv, 7 };
static const rc_memory_regions_t rc_memory_regions_scv = { _rc_memory_regions_scv, 6 };
/* ===== Super Nintendo ===== */
/* https://en.wikibooks.org/wiki/Super_NES_Programming/SNES_memory_map#LoROM */
@ -879,7 +882,7 @@ static const rc_memory_regions_t rc_memory_regions_wonderswan = { _rc_memory_reg
/* ===== default ===== */
static const rc_memory_regions_t rc_memory_regions_none = { 0, 0 };
const rc_memory_regions_t* rc_console_memory_regions(int console_id)
const rc_memory_regions_t* rc_console_memory_regions(uint32_t console_id)
{
switch (console_id)
{

View File

@ -1,6 +1,6 @@
#include "rc_internal.h"
#include "rc_compat.h"
#include "../rc_compat.h"
#include <string.h>
#include <stdio.h>
@ -75,16 +75,16 @@ int rc_parse_format(const char* format_str) {
return RC_FORMAT_VALUE;
}
static int rc_format_value_minutes(char* buffer, int size, unsigned minutes) {
unsigned hours;
static int rc_format_value_minutes(char* buffer, size_t size, uint32_t minutes) {
uint32_t hours;
hours = minutes / 60;
minutes -= hours * 60;
return snprintf(buffer, size, "%uh%02u", hours, minutes);
}
static int rc_format_value_seconds(char* buffer, int size, unsigned seconds) {
unsigned hours, minutes;
static int rc_format_value_seconds(char* buffer, size_t size, uint32_t seconds) {
uint32_t hours, minutes;
/* apply modulus math to split the seconds into hours/minutes/seconds */
minutes = seconds / 60;
@ -98,8 +98,8 @@ static int rc_format_value_seconds(char* buffer, int size, unsigned seconds) {
return snprintf(buffer, size, "%uh%02u:%02u", hours, minutes, seconds);
}
static int rc_format_value_centiseconds(char* buffer, int size, unsigned centiseconds) {
unsigned seconds;
static int rc_format_value_centiseconds(char* buffer, size_t size, uint32_t centiseconds) {
uint32_t seconds;
int chars, chars2;
/* modulus off the centiseconds */
@ -119,7 +119,7 @@ static int rc_format_value_centiseconds(char* buffer, int size, unsigned centise
return chars;
}
int rc_format_typed_value(char* buffer, int size, const rc_typed_value_t* value, int format) {
int rc_format_typed_value(char* buffer, size_t size, const rc_typed_value_t* value, int format) {
int chars;
rc_typed_value_t converted_value;
@ -197,7 +197,7 @@ int rc_format_typed_value(char* buffer, int size, const rc_typed_value_t* value,
return chars;
}
int rc_format_value(char* buffer, int size, int value, int format) {
int rc_format_value(char* buffer, int size, int32_t value, int format) {
rc_typed_value_t typed_value;
typed_value.value.i32 = value;

View File

@ -164,7 +164,7 @@ rc_lboard_t* rc_parse_lboard(void* buffer, const char* memaddr, lua_State* L, in
return (parse.offset >= 0) ? self : 0;
}
int rc_evaluate_lboard(rc_lboard_t* self, int* value, rc_peek_t peek, void* peek_ud, lua_State* L) {
int rc_evaluate_lboard(rc_lboard_t* self, int32_t* value, rc_peek_t peek, void* peek_ud, lua_State* L) {
int start_ok, cancel_ok, submit_ok;
rc_update_memref_values(self->memrefs, peek, peek_ud);
@ -262,6 +262,9 @@ int rc_lboard_state_active(int state) {
}
void rc_reset_lboard(rc_lboard_t* self) {
if (!self)
return;
self->state = RC_LBOARD_STATE_WAITING;
rc_reset_trigger(&self->start);

View File

@ -6,7 +6,7 @@
#define MEMREF_PLACEHOLDER_ADDRESS 0xFFFFFFFF
rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, unsigned address, char size, char is_indirect) {
rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, uint32_t address, uint8_t size, uint8_t is_indirect) {
rc_memref_t** next_memref;
rc_memref_t* memref;
@ -41,7 +41,7 @@ rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, unsigned address, char siz
return memref;
}
int rc_parse_memref(const char** memaddr, char* size, unsigned* address) {
int rc_parse_memref(const char** memaddr, uint8_t* size, uint32_t* address) {
const char* aux = *memaddr;
char* end;
unsigned long value;
@ -114,15 +114,15 @@ int rc_parse_memref(const char** memaddr, char* size, unsigned* address) {
if (value > 0xffffffffU)
value = 0xffffffffU;
*address = (unsigned)value;
*address = (uint32_t)value;
*memaddr = end;
return RC_OK;
}
static float rc_build_float(unsigned mantissa_bits, int exponent, int sign) {
static float rc_build_float(uint32_t mantissa_bits, int32_t exponent, int sign) {
/* 32-bit float has a 23-bit mantissa and 8-bit exponent */
const unsigned implied_bit = 1 << 23;
const unsigned mantissa = mantissa_bits | implied_bit;
const uint32_t implied_bit = 1 << 23;
const uint32_t mantissa = mantissa_bits | implied_bit;
double dbl = ((double)mantissa) / ((double)implied_bit);
if (exponent > 127) {
@ -179,8 +179,8 @@ static float rc_build_float(unsigned mantissa_bits, int exponent, int sign) {
static void rc_transform_memref_float(rc_typed_value_t* value) {
/* decodes an IEEE 754 float */
const unsigned mantissa = (value->value.u32 & 0x7FFFFF);
const int exponent = (int)((value->value.u32 >> 23) & 0xFF) - 127;
const uint32_t mantissa = (value->value.u32 & 0x7FFFFF);
const int32_t exponent = (int32_t)((value->value.u32 >> 23) & 0xFF) - 127;
const int sign = (value->value.u32 & 0x80000000);
value->value.f32 = rc_build_float(mantissa, exponent, sign);
value->type = RC_VALUE_TYPE_FLOAT;
@ -188,11 +188,11 @@ static void rc_transform_memref_float(rc_typed_value_t* value) {
static void rc_transform_memref_float_be(rc_typed_value_t* value) {
/* decodes an IEEE 754 float in big endian format */
const unsigned mantissa = ((value->value.u32 & 0xFF000000) >> 24) |
const uint32_t mantissa = ((value->value.u32 & 0xFF000000) >> 24) |
((value->value.u32 & 0x00FF0000) >> 8) |
((value->value.u32 & 0x00007F00) << 8);
const int exponent = (int)(((value->value.u32 & 0x0000007F) << 1) |
((value->value.u32 & 0x00008000) >> 15)) - 127;
const int32_t exponent = (int32_t)(((value->value.u32 & 0x0000007F) << 1) |
((value->value.u32 & 0x00008000) >> 15)) - 127;
const int sign = (value->value.u32 & 0x00000080);
value->value.f32 = rc_build_float(mantissa, exponent, sign);
value->type = RC_VALUE_TYPE_FLOAT;
@ -201,10 +201,10 @@ static void rc_transform_memref_float_be(rc_typed_value_t* value) {
static void rc_transform_memref_mbf32(rc_typed_value_t* value) {
/* decodes a Microsoft Binary Format float */
/* NOTE: 32-bit MBF is stored in memory as big endian (at least for Apple II) */
const unsigned mantissa = ((value->value.u32 & 0xFF000000) >> 24) |
const uint32_t mantissa = ((value->value.u32 & 0xFF000000) >> 24) |
((value->value.u32 & 0x00FF0000) >> 8) |
((value->value.u32 & 0x00007F00) << 8);
const int exponent = (int)(value->value.u32 & 0xFF) - 129;
const int32_t exponent = (int32_t)(value->value.u32 & 0xFF) - 129;
const int sign = (value->value.u32 & 0x00008000);
if (mantissa == 0 && exponent == -129)
@ -218,8 +218,8 @@ static void rc_transform_memref_mbf32(rc_typed_value_t* value) {
static void rc_transform_memref_mbf32_le(rc_typed_value_t* value) {
/* decodes a Microsoft Binary Format float */
/* Locomotive BASIC (CPC) uses MBF40, but in little endian format */
const unsigned mantissa = value->value.u32 & 0x007FFFFF;
const int exponent = (int)(value->value.u32 >> 24) - 129;
const uint32_t mantissa = value->value.u32 & 0x007FFFFF;
const int32_t exponent = (int32_t)(value->value.u32 >> 24) - 129;
const int sign = (value->value.u32 & 0x00800000);
if (mantissa == 0 && exponent == -129)
@ -230,9 +230,9 @@ static void rc_transform_memref_mbf32_le(rc_typed_value_t* value) {
value->type = RC_VALUE_TYPE_FLOAT;
}
static const unsigned char rc_bits_set[16] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
static const uint8_t rc_bits_set[16] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
void rc_transform_memref_value(rc_typed_value_t* value, char size) {
void rc_transform_memref_value(rc_typed_value_t* value, uint8_t size) {
/* ASSERT: value->type == RC_VALUE_TYPE_UNSIGNED */
switch (size)
{
@ -335,7 +335,7 @@ void rc_transform_memref_value(rc_typed_value_t* value, char size) {
}
}
static const unsigned rc_memref_masks[] = {
static const uint32_t rc_memref_masks[] = {
0x000000ff, /* RC_MEMSIZE_8_BITS */
0x0000ffff, /* RC_MEMSIZE_16_BITS */
0x00ffffff, /* RC_MEMSIZE_24_BITS */
@ -361,7 +361,7 @@ static const unsigned rc_memref_masks[] = {
0xffffffff /* RC_MEMSIZE_VARIABLE */
};
unsigned rc_memref_mask(char size) {
uint32_t rc_memref_mask(uint8_t size) {
const size_t index = (size_t)size;
if (index >= sizeof(rc_memref_masks) / sizeof(rc_memref_masks[0]))
return 0xffffffff;
@ -372,7 +372,7 @@ unsigned rc_memref_mask(char size) {
/* all sizes less than 8-bits (1 byte) are mapped to 8-bits. 24-bit is mapped to 32-bit
* as we don't expect the client to understand a request for 3 bytes. all other reads are
* mapped to the little-endian read of the same size. */
static const char rc_memref_shared_sizes[] = {
static const uint8_t rc_memref_shared_sizes[] = {
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_8_BITS */
RC_MEMSIZE_16_BITS, /* RC_MEMSIZE_16_BITS */
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_24_BITS */
@ -398,7 +398,7 @@ static const char rc_memref_shared_sizes[] = {
RC_MEMSIZE_32_BITS /* RC_MEMSIZE_VARIABLE */
};
char rc_memref_shared_size(char size) {
uint8_t rc_memref_shared_size(uint8_t size) {
const size_t index = (size_t)size;
if (index >= sizeof(rc_memref_shared_sizes) / sizeof(rc_memref_shared_sizes[0]))
return size;
@ -406,7 +406,7 @@ char rc_memref_shared_size(char size) {
return rc_memref_shared_sizes[index];
}
unsigned rc_peek_value(unsigned address, char size, rc_peek_t peek, void* ud) {
uint32_t rc_peek_value(uint32_t address, uint8_t size, rc_peek_t peek, void* ud) {
if (!peek)
return 0;
@ -423,7 +423,7 @@ unsigned rc_peek_value(unsigned address, char size, rc_peek_t peek, void* ud) {
default:
{
unsigned value;
uint32_t value;
const size_t index = (size_t)size;
if (index >= sizeof(rc_memref_shared_sizes) / sizeof(rc_memref_shared_sizes[0]))
return 0;
@ -437,7 +437,7 @@ unsigned rc_peek_value(unsigned address, char size, rc_peek_t peek, void* ud) {
}
}
void rc_update_memref_value(rc_memref_value_t* memref, unsigned new_value) {
void rc_update_memref_value(rc_memref_value_t* memref, uint32_t new_value) {
if (memref->value == new_value) {
memref->changed = 0;
}
@ -463,7 +463,7 @@ void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memref_t** memrefs)
*memrefs = 0;
}
static unsigned rc_get_memref_value_value(const rc_memref_value_t* memref, int operand_type) {
static uint32_t rc_get_memref_value_value(const rc_memref_value_t* memref, int operand_type) {
switch (operand_type)
{
/* most common case explicitly first, even though it could be handled by default case.
@ -483,10 +483,10 @@ static unsigned rc_get_memref_value_value(const rc_memref_value_t* memref, int o
}
}
unsigned rc_get_memref_value(rc_memref_t* memref, int operand_type, rc_eval_state_t* eval_state) {
uint32_t rc_get_memref_value(rc_memref_t* memref, int operand_type, rc_eval_state_t* eval_state) {
/* if this is an indirect reference, handle the indirection. */
if (memref->value.is_indirect) {
const unsigned new_address = memref->address + eval_state->add_address;
const uint32_t new_address = memref->address + eval_state->add_address;
rc_update_memref_value(&memref->value, rc_peek_value(new_address, memref->value.size, eval_state->peek, eval_state->peek_userdata));
}

View File

@ -68,10 +68,10 @@ static int rc_parse_operand_lua(rc_operand_t* self, const char** memaddr, rc_par
return RC_OK;
}
static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse, int is_indirect) {
static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse, uint8_t is_indirect) {
const char* aux = *memaddr;
unsigned address;
char size;
uint32_t address;
uint8_t size;
int ret;
switch (*aux) {
@ -115,7 +115,7 @@ static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_
size = self->size;
}
self->value.memref = rc_alloc_memref(parse, address, size, (char)is_indirect);
self->value.memref = rc_alloc_memref(parse, address, size, is_indirect);
if (parse->offset < 0)
return parse->offset;
@ -123,7 +123,7 @@ static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_
return RC_OK;
}
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_indirect, rc_parse_state_t* parse) {
int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indirect, rc_parse_state_t* parse) {
const char* aux = *memaddr;
char* end;
int ret;
@ -286,11 +286,11 @@ typedef struct {
rc_luapeek_t;
static int rc_luapeek(lua_State* L) {
unsigned address = (unsigned)luaL_checkinteger(L, 1);
unsigned num_bytes = (unsigned)luaL_checkinteger(L, 2);
uint32_t address = (uint32_t)luaL_checkinteger(L, 1);
uint32_t num_bytes = (uint32_t)luaL_checkinteger(L, 2);
rc_luapeek_t* luapeek = (rc_luapeek_t*)lua_touserdata(L, 3);
unsigned value = luapeek->peek(address, num_bytes, luapeek->ud);
uint32_t value = luapeek->peek(address, num_bytes, luapeek->ud);
lua_pushinteger(L, value);
return 1;
@ -330,7 +330,7 @@ int rc_operand_is_float(const rc_operand_t* self) {
return rc_operand_is_float_memref(self);
}
unsigned rc_transform_operand_value(unsigned value, const rc_operand_t* self) {
uint32_t rc_transform_operand_value(uint32_t value, const rc_operand_t* self) {
switch (self->type)
{
case RC_OPERAND_BCD:
@ -451,10 +451,10 @@ void rc_evaluate_operand(rc_typed_value_t* result, rc_operand_t* self, rc_eval_s
if (lua_pcall(eval_state->L, 2, 1, 0) == LUA_OK) {
if (lua_isboolean(eval_state->L, -1)) {
result->value.u32 = (unsigned)lua_toboolean(eval_state->L, -1);
result->value.u32 = (uint32_t)lua_toboolean(eval_state->L, -1);
}
else {
result->value.u32 = (unsigned)lua_tonumber(eval_state->L, -1);
result->value.u32 = (uint32_t)lua_tonumber(eval_state->L, -1);
}
}

View File

@ -1,5 +1,5 @@
#ifndef INTERNAL_H
#define INTERNAL_H
#ifndef RC_INTERNAL_H
#define RC_INTERNAL_H
#include "rc_runtime_types.h"
@ -41,8 +41,8 @@ RC_ALLOW_ALIGN(char)
typedef struct rc_scratch_buffer {
struct rc_scratch_buffer* next;
int offset;
unsigned char buffer[512 - 16];
int32_t offset;
uint8_t buffer[512 - 16];
}
rc_scratch_buffer_t;
@ -77,8 +77,8 @@ enum {
typedef struct {
union {
unsigned u32;
int i32;
uint32_t u32;
int32_t i32;
float f32;
} value;
@ -90,24 +90,24 @@ rc_typed_value_t;
typedef struct {
rc_typed_value_t add_value;/* AddSource/SubSource */
int add_hits; /* AddHits */
unsigned add_address; /* AddAddress */
int32_t add_hits; /* AddHits */
uint32_t add_address; /* AddAddress */
rc_peek_t peek;
void* peek_userdata;
lua_State* L;
rc_typed_value_t measured_value; /* Measured */
char was_reset; /* ResetIf triggered */
char has_hits; /* one of more hit counts is non-zero */
char primed; /* true if all non-Trigger conditions are true */
char measured_from_hits; /* true if the measured_value came from a condition's hit count */
char was_cond_reset; /* ResetNextIf triggered */
uint8_t was_reset; /* ResetIf triggered */
uint8_t has_hits; /* one of more hit counts is non-zero */
uint8_t primed; /* true if all non-Trigger conditions are true */
uint8_t measured_from_hits; /* true if the measured_value came from a condition's hit count */
uint8_t was_cond_reset; /* ResetNextIf triggered */
}
rc_eval_state_t;
typedef struct {
int offset;
int32_t offset;
lua_State* L;
int funcs_ndx;
@ -118,11 +118,11 @@ typedef struct {
rc_memref_t** first_memref;
rc_value_t** variables;
unsigned measured_target;
uint32_t measured_target;
int lines_read;
char has_required_hits;
char measured_as_percent;
uint8_t has_required_hits;
uint8_t measured_as_percent;
}
rc_parse_state_t;
@ -131,21 +131,19 @@ void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memref_t** memrefs)
void rc_init_parse_state_variables(rc_parse_state_t* parse, rc_value_t** variables);
void rc_destroy_parse_state(rc_parse_state_t* parse);
void* rc_alloc(void* pointer, int* offset, int size, int alignment, rc_scratch_t* scratch, int scratch_object_pointer_offset);
void* rc_alloc_scratch(void* pointer, int* offset, int size, int alignment, rc_scratch_t* scratch, int scratch_object_pointer_offset);
char* rc_alloc_str(rc_parse_state_t* parse, const char* text, int length);
void* rc_alloc(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset);
void* rc_alloc_scratch(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset);
char* rc_alloc_str(rc_parse_state_t* parse, const char* text, size_t length);
unsigned rc_djb2(const char* input);
rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, unsigned address, char size, char is_indirect);
int rc_parse_memref(const char** memaddr, char* size, unsigned* address);
rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, uint32_t address, uint8_t size, uint8_t is_indirect);
int rc_parse_memref(const char** memaddr, uint8_t* size, uint32_t* address);
void rc_update_memref_values(rc_memref_t* memref, rc_peek_t peek, void* ud);
void rc_update_memref_value(rc_memref_value_t* memref, unsigned value);
unsigned rc_get_memref_value(rc_memref_t* memref, int operand_type, rc_eval_state_t* eval_state);
char rc_memref_shared_size(char size);
unsigned rc_memref_mask(char size);
void rc_transform_memref_value(rc_typed_value_t* value, char size);
unsigned rc_peek_value(unsigned address, char size, rc_peek_t peek, void* ud);
void rc_update_memref_value(rc_memref_value_t* memref, uint32_t value);
uint32_t rc_get_memref_value(rc_memref_t* memref, int operand_type, rc_eval_state_t* eval_state);
uint8_t rc_memref_shared_size(uint8_t size);
uint32_t rc_memref_mask(uint8_t size);
void rc_transform_memref_value(rc_typed_value_t* value, uint8_t size);
uint32_t rc_peek_value(uint32_t address, uint8_t size, rc_peek_t peek, void* ud);
void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_parse_state_t* parse);
int rc_trigger_state_active(int state);
@ -170,12 +168,12 @@ enum {
RC_PROCESSING_COMPARE_ALWAYS_FALSE
};
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse, int is_indirect);
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse, uint8_t is_indirect);
int rc_test_condition(rc_condition_t* self, rc_eval_state_t* eval_state);
void rc_evaluate_condition_value(rc_typed_value_t* value, rc_condition_t* self, rc_eval_state_t* eval_state);
int rc_condition_is_combining(const rc_condition_t* self);
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_indirect, rc_parse_state_t* parse);
int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indirect, rc_parse_state_t* parse);
void rc_evaluate_operand(rc_typed_value_t* value, rc_operand_t* self, rc_eval_state_t* eval_state);
int rc_operand_is_float_memref(const rc_operand_t* self);
int rc_operand_is_float(const rc_operand_t* self);
@ -184,7 +182,7 @@ void rc_parse_value_internal(rc_value_t* self, const char** memaddr, rc_parse_st
int rc_evaluate_value_typed(rc_value_t* self, rc_typed_value_t* value, rc_peek_t peek, void* ud, lua_State* L);
void rc_reset_value(rc_value_t* self);
int rc_value_from_hits(rc_value_t* self);
rc_value_t* rc_alloc_helper_variable(const char* memaddr, int memaddr_len, rc_parse_state_t* parse);
rc_value_t* rc_alloc_helper_variable(const char* memaddr, size_t memaddr_len, rc_parse_state_t* parse);
void rc_update_variables(rc_value_t* variable, rc_peek_t peek, void* ud, lua_State* L);
void rc_typed_value_convert(rc_typed_value_t* value, char new_type);
@ -195,7 +193,7 @@ void rc_typed_value_negate(rc_typed_value_t* value);
int rc_typed_value_compare(const rc_typed_value_t* value1, const rc_typed_value_t* value2, char oper);
void rc_typed_value_from_memref_value(rc_typed_value_t* value, const rc_memref_value_t* memref);
int rc_format_typed_value(char* buffer, int size, const rc_typed_value_t* value, int format);
int rc_format_typed_value(char* buffer, size_t size, const rc_typed_value_t* value, int format);
void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_state_t* parse);
int rc_lboard_state_active(int state);
@ -206,4 +204,4 @@ void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script,
}
#endif
#endif /* INTERNAL_H */
#endif /* RC_INTERNAL_H */

View File

@ -1,13 +1,14 @@
#include "rc_validate.h"
#include "rc_compat.h"
#include "rc_consoles.h"
#include "rc_internal.h"
#include "../rc_compat.h"
#include <stddef.h>
#include <stdlib.h>
static int rc_validate_memref(const rc_memref_t* memref, char result[], const size_t result_size, int console_id, unsigned max_address)
static int rc_validate_memref(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t console_id, uint32_t max_address)
{
if (memref->address > max_address) {
snprintf(result, result_size, "Address %04X out of range (max %04X)", memref->address, max_address);
@ -41,7 +42,7 @@ static int rc_validate_memref(const rc_memref_t* memref, char result[], const si
return 1;
}
int rc_validate_memrefs(const rc_memref_t* memref, char result[], const size_t result_size, unsigned max_address)
int rc_validate_memrefs(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t max_address)
{
while (memref) {
if (!rc_validate_memref(memref, result, result_size, 0, max_address))
@ -53,7 +54,7 @@ int rc_validate_memrefs(const rc_memref_t* memref, char result[], const size_t r
return 1;
}
static unsigned rc_console_max_address(int console_id)
static uint32_t rc_console_max_address(uint32_t console_id)
{
const rc_memory_regions_t* memory_regions;
memory_regions = rc_console_memory_regions(console_id);
@ -63,9 +64,9 @@ static unsigned rc_console_max_address(int console_id)
return 0xFFFFFFFF;
}
int rc_validate_memrefs_for_console(const rc_memref_t* memref, char result[], const size_t result_size, int console_id)
int rc_validate_memrefs_for_console(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t console_id)
{
const unsigned max_address = rc_console_max_address(console_id);
const uint32_t max_address = rc_console_max_address(console_id);
while (memref) {
if (!rc_validate_memref(memref, result, result_size, console_id, max_address))
return 0;
@ -76,7 +77,7 @@ int rc_validate_memrefs_for_console(const rc_memref_t* memref, char result[], co
return 1;
}
static unsigned rc_max_value(const rc_operand_t* operand)
static uint32_t rc_max_value(const rc_operand_t* operand)
{
if (operand->type == RC_OPERAND_CONST)
return operand->value.num;
@ -118,7 +119,7 @@ static unsigned rc_max_value(const rc_operand_t* operand)
}
}
static unsigned rc_scale_value(unsigned value, char oper, const rc_operand_t* operand)
static uint32_t rc_scale_value(uint32_t value, uint8_t oper, const rc_operand_t* operand)
{
switch (oper) {
case RC_OPERATOR_MULT:
@ -127,12 +128,12 @@ static unsigned rc_scale_value(unsigned value, char oper, const rc_operand_t* op
if (scaled > 0xFFFFFFFF)
return 0xFFFFFFFF;
return (unsigned)scaled;
return (uint32_t)scaled;
}
case RC_OPERATOR_DIV:
{
const unsigned min_val = (operand->type == RC_OPERAND_CONST) ? operand->value.num : 1;
const uint32_t min_val = (operand->type == RC_OPERAND_CONST) ? operand->value.num : 1;
return value / min_val;
}
@ -162,7 +163,7 @@ static int rc_validate_get_condition_index(const rc_condset_t* condset, const rc
return 0;
}
static int rc_validate_range(unsigned min_val, unsigned max_val, char oper, unsigned max, char result[], const size_t result_size)
static int rc_validate_range(uint32_t min_val, uint32_t max_val, char oper, uint32_t max, char result[], const size_t result_size)
{
switch (oper) {
case RC_OPERATOR_AND:
@ -230,11 +231,11 @@ static int rc_validate_range(unsigned min_val, unsigned max_val, char oper, unsi
return 1;
}
int rc_validate_condset_internal(const rc_condset_t* condset, char result[], const size_t result_size, int console_id, unsigned max_address)
int rc_validate_condset_internal(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t console_id, uint32_t max_address)
{
const rc_condition_t* cond;
char buffer[128];
unsigned max_val;
uint32_t max_val;
int index = 1;
unsigned long long add_source_max = 0;
int in_add_hits = 0;
@ -247,7 +248,7 @@ int rc_validate_condset_internal(const rc_condset_t* condset, char result[], con
}
for (cond = condset->conditions; cond; cond = cond->next, ++index) {
unsigned max = rc_max_value(&cond->operand1);
uint32_t max = rc_max_value(&cond->operand1);
const int is_memref1 = rc_operand_is_memref(&cond->operand1);
const int is_memref2 = rc_operand_is_memref(&cond->operand2);
@ -300,6 +301,13 @@ int rc_validate_condset_internal(const rc_condset_t* condset, char result[], con
is_combining = 1;
break;
case RC_CONDITION_RESET_IF:
if (cond->required_hits == 1) {
snprintf(result, result_size, "Condition %d: Hit target of 1 is redundant on ResetIf", index);
return 0;
}
/* fallthrough to default */
default:
if (in_add_hits) {
if (cond->required_hits == 0) {
@ -334,7 +342,7 @@ int rc_validate_condset_internal(const rc_condset_t* condset, char result[], con
if (is_memref1 || is_memref2 || add_source_max) {
const size_t prefix_length = snprintf(result, result_size, "Condition %d: ", index);
unsigned min_val;
uint32_t min_val;
switch (cond->operand2.type) {
case RC_OPERAND_CONST:
min_val = cond->operand2.value.num;
@ -386,14 +394,14 @@ int rc_validate_condset_internal(const rc_condset_t* condset, char result[], con
return 1;
}
int rc_validate_condset(const rc_condset_t* condset, char result[], const size_t result_size, unsigned max_address)
int rc_validate_condset(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t max_address)
{
return rc_validate_condset_internal(condset, result, result_size, 0, max_address);
}
int rc_validate_condset_for_console(const rc_condset_t* condset, char result[], const size_t result_size, int console_id)
int rc_validate_condset_for_console(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t console_id)
{
const unsigned max_address = rc_console_max_address(console_id);
const uint32_t max_address = rc_console_max_address(console_id);
return rc_validate_condset_internal(condset, result, result_size, console_id, max_address);
}
@ -476,7 +484,7 @@ enum {
RC_OVERLAP_DEFER
};
static int rc_validate_comparison_overlap(int comparison1, unsigned value1, int comparison2, unsigned value2)
static int rc_validate_comparison_overlap(int comparison1, uint32_t value1, int comparison2, uint32_t value2)
{
/* NOTE: this only cares if comp2 conflicts with comp1.
* If comp1 conflicts with comp2, we'll catch that later (return RC_OVERLAP_NONE for now) */
@ -634,7 +642,7 @@ static int rc_validate_conflicting_conditions(const rc_condset_t* conditions, co
const char* prefix, const char* compare_prefix, char result[], const size_t result_size)
{
int comparison1, comparison2;
unsigned value1, value2;
uint32_t value1, value2;
const rc_operand_t* operand1;
const rc_operand_t* operand2;
const rc_condition_t* compare_condition;
@ -789,7 +797,7 @@ static int rc_validate_conflicting_conditions(const rc_condset_t* conditions, co
return 1;
}
static int rc_validate_trigger_internal(const rc_trigger_t* trigger, char result[], const size_t result_size, int console_id, unsigned max_address)
static int rc_validate_trigger_internal(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t console_id, uint32_t max_address)
{
const rc_condset_t* alt;
int index;
@ -835,13 +843,13 @@ static int rc_validate_trigger_internal(const rc_trigger_t* trigger, char result
return 1;
}
int rc_validate_trigger(const rc_trigger_t* trigger, char result[], const size_t result_size, unsigned max_address)
int rc_validate_trigger(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t max_address)
{
return rc_validate_trigger_internal(trigger, result, result_size, 0, max_address);
}
int rc_validate_trigger_for_console(const rc_trigger_t* trigger, char result[], const size_t result_size, int console_id)
int rc_validate_trigger_for_console(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t console_id)
{
const unsigned max_address = rc_console_max_address(console_id);
const uint32_t max_address = rc_console_max_address(console_id);
return rc_validate_trigger_internal(trigger, result, result_size, console_id, max_address);
}

View File

@ -9,15 +9,15 @@
extern "C" {
#endif
int rc_validate_memrefs(const rc_memref_t* memref, char result[], const size_t result_size, unsigned max_address);
int rc_validate_memrefs(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t max_address);
int rc_validate_condset(const rc_condset_t* condset, char result[], const size_t result_size, unsigned max_address);
int rc_validate_trigger(const rc_trigger_t* trigger, char result[], const size_t result_size, unsigned max_address);
int rc_validate_condset(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t max_address);
int rc_validate_trigger(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t max_address);
int rc_validate_memrefs_for_console(const rc_memref_t* memref, char result[], const size_t result_size, int console_id);
int rc_validate_memrefs_for_console(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t console_id);
int rc_validate_condset_for_console(const rc_condset_t* condset, char result[], const size_t result_size, int console_id);
int rc_validate_trigger_for_console(const rc_trigger_t* trigger, char result[], const size_t result_size, int console_id);
int rc_validate_condset_for_console(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t console_id);
int rc_validate_trigger_for_console(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t console_id);
#ifdef __cplusplus
}

View File

@ -1,6 +1,6 @@
#include "rc_internal.h"
#include "rc_compat.h"
#include "../rc_compat.h"
#include <ctype.h>
@ -16,8 +16,8 @@ enum {
static rc_memref_value_t* rc_alloc_helper_variable_memref_value(const char* memaddr, int memaddr_len, rc_parse_state_t* parse) {
const char* end;
rc_value_t* variable;
unsigned address;
char size;
uint32_t address;
uint8_t size;
/* single memory reference lookups without a modifier flag can be handled without a variable */
end = memaddr;
@ -78,7 +78,7 @@ static const char* rc_parse_line(const char* line, const char** end, rc_parse_st
typedef struct rc_richpresence_builtin_macro_t {
const char* name;
size_t name_len;
unsigned short display_type;
uint8_t display_type;
} rc_richpresence_builtin_macro_t;
static rc_richpresence_display_t* rc_parse_richpresence_display_internal(const char* line, const char* endline, rc_parse_state_t* parse, rc_richpresence_lookup_t* first_lookup) {
@ -324,7 +324,7 @@ static void rc_rebalance_richpresence_lookup(rc_richpresence_lookup_item_t** roo
}
static void rc_insert_richpresence_lookup_item(rc_richpresence_lookup_t* lookup,
unsigned first, unsigned last, const char* label, int label_len, rc_parse_state_t* parse)
uint32_t first, uint32_t last, const char* label, size_t label_len, rc_parse_state_t* parse)
{
rc_richpresence_lookup_item_t** next;
rc_richpresence_lookup_item_t* item;
@ -370,7 +370,7 @@ static const char* rc_parse_richpresence_lookup(rc_richpresence_lookup_t* lookup
const char* endline;
const char* label;
char* endptr = 0;
unsigned first, last;
uint32_t first, last;
int base;
do
@ -525,7 +525,7 @@ void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script,
memcpy(format, line, chars);
format[chars] = '\0';
lookup->format = (unsigned short)rc_parse_format(format);
lookup->format = (uint8_t)rc_parse_format(format);
} else {
lookup->format = RC_FORMAT_VALUE;
}
@ -663,7 +663,7 @@ void rc_update_richpresence(rc_richpresence_t* richpresence, rc_peek_t peek, voi
}
}
static int rc_evaluate_richpresence_display(rc_richpresence_display_part_t* part, char* buffer, unsigned buffersize)
static int rc_evaluate_richpresence_display(rc_richpresence_display_part_t* part, char* buffer, size_t buffersize)
{
rc_richpresence_lookup_item_t* item;
rc_typed_value_t value;
@ -807,7 +807,7 @@ static int rc_evaluate_richpresence_display(rc_richpresence_display_part_t* part
return (int)(ptr - buffer);
}
int rc_get_richpresence_display_string(rc_richpresence_t* richpresence, char* buffer, unsigned buffersize, rc_peek_t peek, void* peek_ud, lua_State* L) {
int rc_get_richpresence_display_string(rc_richpresence_t* richpresence, char* buffer, size_t buffersize, rc_peek_t peek, void* peek_ud, lua_State* L) {
rc_richpresence_display_t* display;
for (display = richpresence->first_display; display; display = display->next) {
@ -828,7 +828,7 @@ int rc_get_richpresence_display_string(rc_richpresence_t* richpresence, char* bu
return 0;
}
int rc_evaluate_richpresence(rc_richpresence_t* richpresence, char* buffer, unsigned buffersize, rc_peek_t peek, void* peek_ud, lua_State* L) {
int rc_evaluate_richpresence(rc_richpresence_t* richpresence, char* buffer, size_t buffersize, rc_peek_t peek, void* peek_ud, lua_State* L) {
rc_update_richpresence(richpresence, peek, peek_ud, L);
return rc_get_richpresence_display_string(richpresence, buffer, buffersize, peek, peek_ud, L);
}

View File

@ -1,7 +1,7 @@
#include "rc_runtime.h"
#include "rc_internal.h"
#include "rc_compat.h"
#include "../rc_compat.h"
#include "../rhash/md5.h"
#include <stdlib.h>
@ -27,7 +27,7 @@ void rc_runtime_init(rc_runtime_t* self) {
}
void rc_runtime_destroy(rc_runtime_t* self) {
unsigned i;
uint32_t i;
if (self->triggers) {
for (i = 0; i < self->trigger_count; ++i)
@ -65,7 +65,7 @@ void rc_runtime_destroy(rc_runtime_t* self) {
}
}
void rc_runtime_checksum(const char* memaddr, unsigned char* md5) {
void rc_runtime_checksum(const char* memaddr, uint8_t* md5) {
md5_state_t state;
md5_init(&state);
md5_append(&state, (unsigned char*)memaddr, (int)strlen(memaddr));
@ -96,7 +96,7 @@ static char rc_runtime_allocated_memrefs(rc_runtime_t* self) {
return owns_memref;
}
static void rc_runtime_deactivate_trigger_by_index(rc_runtime_t* self, unsigned index) {
static void rc_runtime_deactivate_trigger_by_index(rc_runtime_t* self, uint32_t index) {
if (self->triggers[index].owns_memrefs) {
/* if the trigger has one or more memrefs in its buffer, we can't free the buffer.
* just null out the trigger so the runtime processor will skip it
@ -113,8 +113,8 @@ static void rc_runtime_deactivate_trigger_by_index(rc_runtime_t* self, unsigned
}
}
void rc_runtime_deactivate_achievement(rc_runtime_t* self, unsigned id) {
unsigned i;
void rc_runtime_deactivate_achievement(rc_runtime_t* self, uint32_t id) {
uint32_t i;
for (i = 0; i < self->trigger_count; ++i) {
if (self->triggers[i].id == id && self->triggers[i].trigger != NULL)
@ -122,14 +122,14 @@ void rc_runtime_deactivate_achievement(rc_runtime_t* self, unsigned id) {
}
}
int rc_runtime_activate_achievement(rc_runtime_t* self, unsigned id, const char* memaddr, lua_State* L, int funcs_idx) {
int rc_runtime_activate_achievement(rc_runtime_t* self, uint32_t id, const char* memaddr, lua_State* L, int funcs_idx) {
void* trigger_buffer;
rc_trigger_t* trigger;
rc_runtime_trigger_t* runtime_trigger;
rc_parse_state_t parse;
unsigned char md5[16];
int size;
unsigned i;
uint8_t md5[16];
int32_t size;
uint32_t i;
if (memaddr == NULL)
return RC_INVALID_MEMORY_OPERAND;
@ -222,9 +222,9 @@ int rc_runtime_activate_achievement(rc_runtime_t* self, unsigned id, const char*
return RC_OK;
}
rc_trigger_t* rc_runtime_get_achievement(const rc_runtime_t* self, unsigned id)
rc_trigger_t* rc_runtime_get_achievement(const rc_runtime_t* self, uint32_t id)
{
unsigned i;
uint32_t i;
for (i = 0; i < self->trigger_count; ++i) {
if (self->triggers[i].id == id && self->triggers[i].trigger != NULL)
@ -234,7 +234,7 @@ rc_trigger_t* rc_runtime_get_achievement(const rc_runtime_t* self, unsigned id)
return NULL;
}
int rc_runtime_get_achievement_measured(const rc_runtime_t* runtime, unsigned id, unsigned* measured_value, unsigned* measured_target)
int rc_runtime_get_achievement_measured(const rc_runtime_t* runtime, uint32_t id, unsigned* measured_value, unsigned* measured_target)
{
const rc_trigger_t* trigger = rc_runtime_get_achievement(runtime, id);
if (!measured_value || !measured_target)
@ -257,10 +257,10 @@ int rc_runtime_get_achievement_measured(const rc_runtime_t* runtime, unsigned id
return 1;
}
int rc_runtime_format_achievement_measured(const rc_runtime_t* runtime, unsigned id, char* buffer, size_t buffer_size)
int rc_runtime_format_achievement_measured(const rc_runtime_t* runtime, uint32_t id, char* buffer, size_t buffer_size)
{
const rc_trigger_t* trigger = rc_runtime_get_achievement(runtime, id);
unsigned value;
uint32_t value;
if (!buffer || !buffer_size)
return 0;
@ -277,14 +277,14 @@ int rc_runtime_format_achievement_measured(const rc_runtime_t* runtime, unsigned
value = trigger->measured_target;
if (trigger->measured_as_percent) {
unsigned percent = (unsigned)(((unsigned long long)value * 100) / trigger->measured_target);
const uint32_t percent = (uint32_t)(((unsigned long long)value * 100) / trigger->measured_target);
return snprintf(buffer, buffer_size, "%u%%", percent);
}
return snprintf(buffer, buffer_size, "%u/%u", value, trigger->measured_target);
}
static void rc_runtime_deactivate_lboard_by_index(rc_runtime_t* self, unsigned index) {
static void rc_runtime_deactivate_lboard_by_index(rc_runtime_t* self, uint32_t index) {
if (self->lboards[index].owns_memrefs) {
/* if the lboard has one or more memrefs in its buffer, we can't free the buffer.
* just null out the lboard so the runtime processor will skip it
@ -301,8 +301,8 @@ static void rc_runtime_deactivate_lboard_by_index(rc_runtime_t* self, unsigned i
}
}
void rc_runtime_deactivate_lboard(rc_runtime_t* self, unsigned id) {
unsigned i;
void rc_runtime_deactivate_lboard(rc_runtime_t* self, uint32_t id) {
uint32_t i;
for (i = 0; i < self->lboard_count; ++i) {
if (self->lboards[i].id == id && self->lboards[i].lboard != NULL)
@ -310,14 +310,14 @@ void rc_runtime_deactivate_lboard(rc_runtime_t* self, unsigned id) {
}
}
int rc_runtime_activate_lboard(rc_runtime_t* self, unsigned id, const char* memaddr, lua_State* L, int funcs_idx) {
int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* memaddr, lua_State* L, int funcs_idx) {
void* lboard_buffer;
unsigned char md5[16];
uint8_t md5[16];
rc_lboard_t* lboard;
rc_parse_state_t parse;
rc_runtime_lboard_t* runtime_lboard;
int size;
unsigned i;
uint32_t i;
if (memaddr == 0)
return RC_INVALID_MEMORY_OPERAND;
@ -410,9 +410,9 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, unsigned id, const char* mema
return RC_OK;
}
rc_lboard_t* rc_runtime_get_lboard(const rc_runtime_t* self, unsigned id)
rc_lboard_t* rc_runtime_get_lboard(const rc_runtime_t* self, uint32_t id)
{
unsigned i;
uint32_t i;
for (i = 0; i < self->lboard_count; ++i) {
if (self->lboards[i].id == id && self->lboards[i].lboard != NULL)
@ -422,7 +422,7 @@ rc_lboard_t* rc_runtime_get_lboard(const rc_runtime_t* self, unsigned id)
return NULL;
}
int rc_runtime_format_lboard_value(char* buffer, int size, int value, int format)
int rc_runtime_format_lboard_value(char* buffer, int size, int32_t value, int format)
{
return rc_format_value(buffer, size, value, format);
}
@ -432,7 +432,7 @@ int rc_runtime_activate_richpresence(rc_runtime_t* self, const char* script, lua
rc_runtime_richpresence_t* previous;
rc_runtime_richpresence_t** previous_ptr;
rc_parse_state_t parse;
unsigned char md5[16];
uint8_t md5[16];
int size;
if (script == NULL)
@ -529,7 +529,7 @@ int rc_runtime_activate_richpresence(rc_runtime_t* self, const char* script, lua
return RC_OK;
}
int rc_runtime_get_richpresence(const rc_runtime_t* self, char* buffer, unsigned buffersize, rc_runtime_peek_t peek, void* peek_ud, lua_State* L) {
int rc_runtime_get_richpresence(const rc_runtime_t* self, char* buffer, size_t buffersize, rc_runtime_peek_t peek, void* peek_ud, lua_State* L) {
if (self->richpresence && self->richpresence->richpresence)
return rc_get_richpresence_display_string(self->richpresence->richpresence, buffer, buffersize, peek, peek_ud, L);
@ -549,7 +549,7 @@ void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_ha
for (i = self->trigger_count - 1; i >= 0; --i) {
rc_trigger_t* trigger = self->triggers[i].trigger;
int old_state, new_state;
unsigned old_measured_value;
uint32_t old_measured_value;
if (!trigger)
continue;
@ -593,8 +593,8 @@ void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_ha
if (trigger->measured_as_percent) {
/* if reporting measured value as a percentage, only send the notification if the percentage changes */
unsigned old_percent = (unsigned)(((unsigned long long)old_measured_value * 100) / trigger->measured_target);
unsigned new_percent = (unsigned)(((unsigned long long)trigger->measured_value * 100) / trigger->measured_target);
const int32_t old_percent = (int32_t)(((unsigned long long)old_measured_value * 100) / trigger->measured_target);
const int32_t new_percent = (int32_t)(((unsigned long long)trigger->measured_value * 100) / trigger->measured_target);
if (old_percent != new_percent) {
runtime_event.value = new_percent;
event_handler(&runtime_event);
@ -715,7 +715,7 @@ void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_ha
void rc_runtime_reset(rc_runtime_t* self) {
rc_value_t* variable;
unsigned i;
uint32_t i;
for (i = 0; i < self->trigger_count; ++i) {
if (self->triggers[i].trigger)
@ -779,7 +779,7 @@ int rc_trigger_contains_memref(const rc_trigger_t* trigger, const rc_memref_t* m
}
static void rc_runtime_invalidate_memref(rc_runtime_t* self, rc_memref_t* memref) {
unsigned i;
uint32_t i;
/* disable any achievements dependent on the address */
for (i = 0; i < self->trigger_count; ++i) {
@ -814,7 +814,7 @@ static void rc_runtime_invalidate_memref(rc_runtime_t* self, rc_memref_t* memref
}
}
void rc_runtime_invalidate_address(rc_runtime_t* self, unsigned address) {
void rc_runtime_invalidate_address(rc_runtime_t* self, uint32_t address) {
rc_memref_t** last_memref = &self->memrefs;
rc_memref_t* memref = self->memrefs;

View File

@ -1,6 +1,7 @@
#include "rc_runtime.h"
#include "rc_internal.h"
#include "../rc_util.h"
#include "../rhash/md5.h"
#include <stdlib.h>
@ -19,10 +20,10 @@
typedef struct rc_runtime_progress_t {
const rc_runtime_t* runtime;
int offset;
unsigned char* buffer;
uint32_t offset;
uint8_t* buffer;
int chunk_size_offset;
uint32_t chunk_size_offset;
lua_State* L;
} rc_runtime_progress_t;
@ -39,7 +40,7 @@ typedef struct rc_runtime_progress_t {
#define RC_COND_FLAG_OPERAND2_IS_INDIRECT_MEMREF 0x00100000
#define RC_COND_FLAG_OPERAND2_MEMREF_CHANGED_THIS_FRAME 0x00200000
static void rc_runtime_progress_write_uint(rc_runtime_progress_t* progress, unsigned value)
static void rc_runtime_progress_write_uint(rc_runtime_progress_t* progress, uint32_t value)
{
if (progress->buffer) {
progress->buffer[progress->offset + 0] = value & 0xFF; value >>= 8;
@ -51,9 +52,9 @@ static void rc_runtime_progress_write_uint(rc_runtime_progress_t* progress, unsi
progress->offset += 4;
}
static unsigned rc_runtime_progress_read_uint(rc_runtime_progress_t* progress)
static uint32_t rc_runtime_progress_read_uint(rc_runtime_progress_t* progress)
{
unsigned value = progress->buffer[progress->offset + 0] |
uint32_t value = progress->buffer[progress->offset + 0] |
(progress->buffer[progress->offset + 1] << 8) |
(progress->buffer[progress->offset + 2] << 16) |
(progress->buffer[progress->offset + 3] << 24);
@ -62,7 +63,7 @@ static unsigned rc_runtime_progress_read_uint(rc_runtime_progress_t* progress)
return value;
}
static void rc_runtime_progress_write_md5(rc_runtime_progress_t* progress, unsigned char* md5)
static void rc_runtime_progress_write_md5(rc_runtime_progress_t* progress, uint8_t* md5)
{
if (progress->buffer)
memcpy(&progress->buffer[progress->offset], md5, 16);
@ -70,7 +71,7 @@ static void rc_runtime_progress_write_md5(rc_runtime_progress_t* progress, unsig
progress->offset += 16;
}
static int rc_runtime_progress_match_md5(rc_runtime_progress_t* progress, unsigned char* md5)
static int rc_runtime_progress_match_md5(rc_runtime_progress_t* progress, uint8_t* md5)
{
int result = 0;
if (progress->buffer)
@ -81,7 +82,7 @@ static int rc_runtime_progress_match_md5(rc_runtime_progress_t* progress, unsign
return result;
}
static void rc_runtime_progress_start_chunk(rc_runtime_progress_t* progress, unsigned chunk_id)
static void rc_runtime_progress_start_chunk(rc_runtime_progress_t* progress, uint32_t chunk_id)
{
rc_runtime_progress_write_uint(progress, chunk_id);
@ -92,14 +93,14 @@ static void rc_runtime_progress_start_chunk(rc_runtime_progress_t* progress, uns
static void rc_runtime_progress_end_chunk(rc_runtime_progress_t* progress)
{
unsigned length;
int offset;
uint32_t length;
uint32_t offset;
progress->offset = (progress->offset + 3) & ~0x03; /* align to 4 byte boundary */
if (progress->buffer) {
/* ignore chunk size field when calculating chunk size */
length = (unsigned)(progress->offset - progress->chunk_size_offset - 4);
length = (uint32_t)(progress->offset - progress->chunk_size_offset - 4);
/* temporarily update the write pointer to write the chunk size field */
offset = progress->offset;
@ -119,7 +120,7 @@ static void rc_runtime_progress_init(rc_runtime_progress_t* progress, const rc_r
static int rc_runtime_progress_write_memrefs(rc_runtime_progress_t* progress)
{
rc_memref_t* memref = progress->runtime->memrefs;
unsigned int flags = 0;
uint32_t flags = 0;
rc_runtime_progress_start_chunk(progress, RC_RUNTIME_CHUNK_MEMREFS);
@ -150,9 +151,9 @@ static int rc_runtime_progress_write_memrefs(rc_runtime_progress_t* progress)
static int rc_runtime_progress_read_memrefs(rc_runtime_progress_t* progress)
{
unsigned entries;
unsigned address, flags, value, prior;
char size;
uint32_t entries;
uint32_t address, flags, value, prior;
uint8_t size;
rc_memref_t* memref;
rc_memref_t* first_unmatched_memref = progress->runtime->memrefs;
@ -207,7 +208,7 @@ static int rc_runtime_progress_is_indirect_memref(rc_operand_t* oper)
static int rc_runtime_progress_write_condset(rc_runtime_progress_t* progress, rc_condset_t* condset)
{
rc_condition_t* cond;
unsigned flags;
uint32_t flags;
rc_runtime_progress_write_uint(progress, condset->is_paused);
@ -251,7 +252,7 @@ static int rc_runtime_progress_write_condset(rc_runtime_progress_t* progress, rc
static int rc_runtime_progress_read_condset(rc_runtime_progress_t* progress, rc_condset_t* condset)
{
rc_condition_t* cond;
unsigned flags;
uint32_t flags;
condset->is_paused = (char)rc_runtime_progress_read_uint(progress);
@ -286,7 +287,7 @@ static int rc_runtime_progress_read_condset(rc_runtime_progress_t* progress, rc_
return RC_OK;
}
static unsigned rc_runtime_progress_should_serialize_variable_condset(const rc_condset_t* conditions)
static uint32_t rc_runtime_progress_should_serialize_variable_condset(const rc_condset_t* conditions)
{
const rc_condition_t* condition;
@ -307,7 +308,7 @@ static unsigned rc_runtime_progress_should_serialize_variable_condset(const rc_c
static int rc_runtime_progress_write_variable(rc_runtime_progress_t* progress, const rc_value_t* variable)
{
unsigned flags;
uint32_t flags;
flags = rc_runtime_progress_should_serialize_variable_condset(variable->conditions);
if (variable->value.changed)
@ -328,7 +329,7 @@ static int rc_runtime_progress_write_variable(rc_runtime_progress_t* progress, c
static int rc_runtime_progress_write_variables(rc_runtime_progress_t* progress)
{
unsigned count = 0;
uint32_t count = 0;
const rc_value_t* variable;
for (variable = progress->runtime->variables; variable; variable = variable->next)
@ -341,7 +342,7 @@ static int rc_runtime_progress_write_variables(rc_runtime_progress_t* progress)
for (variable = progress->runtime->variables; variable; variable = variable->next)
{
unsigned djb2 = rc_djb2(variable->name);
uint32_t djb2 = rc_djb2(variable->name);
rc_runtime_progress_write_uint(progress, djb2);
rc_runtime_progress_write_variable(progress, variable);
@ -353,7 +354,7 @@ static int rc_runtime_progress_write_variables(rc_runtime_progress_t* progress)
static int rc_runtime_progress_read_variable(rc_runtime_progress_t* progress, rc_value_t* variable)
{
unsigned flags = rc_runtime_progress_read_uint(progress);
uint32_t flags = rc_runtime_progress_read_uint(progress);
variable->value.changed = (flags & RC_MEMREF_FLAG_CHANGED_THIS_FRAME) ? 1 : 0;
variable->value.value = rc_runtime_progress_read_uint(progress);
variable->value.prior = rc_runtime_progress_read_uint(progress);
@ -375,14 +376,14 @@ static int rc_runtime_progress_read_variables(rc_runtime_progress_t* progress)
struct rc_pending_value_t
{
rc_value_t* variable;
unsigned djb2;
uint32_t djb2;
};
struct rc_pending_value_t local_pending_variables[32];
struct rc_pending_value_t* pending_variables;
rc_value_t* variable;
unsigned count, serialized_count;
uint32_t count, serialized_count;
int result;
unsigned i;
uint32_t i;
serialized_count = rc_runtime_progress_read_uint(progress);
if (serialized_count == 0)
@ -413,7 +414,7 @@ static int rc_runtime_progress_read_variables(rc_runtime_progress_t* progress)
result = RC_OK;
for (; serialized_count > 0 && result == RC_OK; --serialized_count) {
unsigned djb2 = rc_runtime_progress_read_uint(progress);
uint32_t djb2 = rc_runtime_progress_read_uint(progress);
for (i = 0; i < count; ++i) {
if (pending_variables[i].djb2 == djb2) {
variable = pending_variables[i].variable;
@ -491,7 +492,7 @@ static int rc_runtime_progress_read_trigger(rc_runtime_progress_t* progress, rc_
static int rc_runtime_progress_write_achievements(rc_runtime_progress_t* progress)
{
unsigned i;
uint32_t i;
int offset = 0;
int result;
@ -532,8 +533,8 @@ static int rc_runtime_progress_write_achievements(rc_runtime_progress_t* progres
static int rc_runtime_progress_read_achievement(rc_runtime_progress_t* progress)
{
unsigned id = rc_runtime_progress_read_uint(progress);
unsigned i;
uint32_t id = rc_runtime_progress_read_uint(progress);
uint32_t i;
for (i = 0; i < progress->runtime->trigger_count; ++i) {
rc_runtime_trigger_t* runtime_trigger = &progress->runtime->triggers[i];
@ -553,8 +554,8 @@ static int rc_runtime_progress_read_achievement(rc_runtime_progress_t* progress)
static int rc_runtime_progress_write_leaderboards(rc_runtime_progress_t* progress)
{
unsigned i;
unsigned flags;
uint32_t i;
uint32_t flags;
int offset = 0;
int result;
@ -610,8 +611,8 @@ static int rc_runtime_progress_write_leaderboards(rc_runtime_progress_t* progres
static int rc_runtime_progress_read_leaderboard(rc_runtime_progress_t* progress)
{
unsigned id = rc_runtime_progress_read_uint(progress);
unsigned i;
uint32_t id = rc_runtime_progress_read_uint(progress);
uint32_t i;
int result;
for (i = 0; i < progress->runtime->lboard_count; ++i) {
@ -621,7 +622,7 @@ static int rc_runtime_progress_read_leaderboard(rc_runtime_progress_t* progress)
if (runtime_lboard->lboard->state == RC_TRIGGER_STATE_UNUPDATED) {
/* only update state if definition hasn't changed (md5 matches) */
if (rc_runtime_progress_match_md5(progress, runtime_lboard->md5)) {
unsigned flags = rc_runtime_progress_read_uint(progress);
uint32_t flags = rc_runtime_progress_read_uint(progress);
result = rc_runtime_progress_read_trigger(progress, &runtime_lboard->lboard->start);
if (result != RC_OK)
@ -701,7 +702,7 @@ static int rc_runtime_progress_read_rich_presence(rc_runtime_progress_t* progres
static int rc_runtime_progress_serialize_internal(rc_runtime_progress_t* progress)
{
md5_state_t state;
unsigned char md5[16];
uint8_t md5[16];
int result;
rc_runtime_progress_write_uint(progress, RC_RUNTIME_MARKER);
@ -757,20 +758,20 @@ int rc_runtime_serialize_progress(void* buffer, const rc_runtime_t* runtime, lua
return RC_INVALID_STATE;
rc_runtime_progress_init(&progress, runtime, L);
progress.buffer = (unsigned char*)buffer;
progress.buffer = (uint8_t*)buffer;
return rc_runtime_progress_serialize_internal(&progress);
}
int rc_runtime_deserialize_progress(rc_runtime_t* runtime, const unsigned char* serialized, lua_State* L)
int rc_runtime_deserialize_progress(rc_runtime_t* runtime, const uint8_t* serialized, lua_State* L)
{
rc_runtime_progress_t progress;
md5_state_t state;
unsigned char md5[16];
unsigned chunk_id;
unsigned chunk_size;
unsigned next_chunk_offset;
unsigned i;
uint8_t md5[16];
uint32_t chunk_id;
uint32_t chunk_size;
uint32_t next_chunk_offset;
uint32_t i;
int seen_rich_presence = 0;
int result = RC_OK;
@ -780,7 +781,7 @@ int rc_runtime_deserialize_progress(rc_runtime_t* runtime, const unsigned char*
}
rc_runtime_progress_init(&progress, runtime, L);
progress.buffer = (unsigned char*)serialized;
progress.buffer = (uint8_t*)serialized;
if (rc_runtime_progress_read_uint(&progress) != RC_RUNTIME_MARKER) {
rc_runtime_reset(runtime);

View File

@ -96,7 +96,7 @@ int rc_trigger_state_active(int state)
}
}
static int rc_condset_is_measured_from_hitcount(const rc_condset_t* condset, unsigned measured_value)
static int rc_condset_is_measured_from_hitcount(const rc_condset_t* condset, uint32_t measured_value)
{
const rc_condition_t* condition;
for (condition = condset->conditions; condition; condition = condition->next) {
@ -280,6 +280,9 @@ int rc_test_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State* L)
}
void rc_reset_trigger(rc_trigger_t* self) {
if (!self)
return;
rc_reset_trigger_hitcounts(self);
self->state = RC_TRIGGER_STATE_WAITING;

View File

@ -255,7 +255,7 @@ int rc_evaluate_value_typed(rc_value_t* self, rc_typed_value_t* value, rc_peek_t
return valid;
}
int rc_evaluate_value(rc_value_t* self, rc_peek_t peek, void* ud, lua_State* L) {
int32_t rc_evaluate_value(rc_value_t* self, rc_peek_t peek, void* ud, lua_State* L) {
rc_typed_value_t result;
int valid = rc_evaluate_value_typed(self, &result, peek, ud, L);
@ -304,12 +304,12 @@ void rc_init_parse_state_variables(rc_parse_state_t* parse, rc_value_t** variabl
*variables = 0;
}
rc_value_t* rc_alloc_helper_variable(const char* memaddr, int memaddr_len, rc_parse_state_t* parse)
rc_value_t* rc_alloc_helper_variable(const char* memaddr, size_t memaddr_len, rc_parse_state_t* parse)
{
rc_value_t** variables = parse->variables;
rc_value_t* value;
const char* name;
unsigned measured_target;
uint32_t measured_target;
while ((value = *variables) != NULL) {
if (strncmp(value->name, memaddr, memaddr_len) == 0 && value->name[memaddr_len] == 0)

View File

@ -1,6 +1,6 @@
#include "rc_hash.h"
#include "../rcheevos/rc_compat.h"
#include "../rc_compat.h"
#include <ctype.h>
#include <string.h>
@ -31,7 +31,7 @@ struct cdrom_t
#endif
};
static int cdreader_get_sector(unsigned char header[16])
static int cdreader_get_sector(uint8_t header[16])
{
int minutes = (header[12] >> 4) * 10 + (header[12] & 0x0F);
int seconds = (header[13] >> 4) * 10 + (header[13] & 0x0F);
@ -50,11 +50,11 @@ static void cdreader_determine_sector_size(struct cdrom_t* cdrom)
* Then check for the presence of "CD001", which is gauranteed to be in either the
* boot record or primary volume descriptor, one of which is always at sector 16.
*/
const unsigned char sync_pattern[] = {
const uint8_t sync_pattern[] = {
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
};
unsigned char header[32];
uint8_t header[32];
const int64_t toc_sector = 16 + cdrom->track_pregap_sectors;
cdrom->sector_size = 0;

View File

@ -1,6 +1,6 @@
#include "rc_hash.h"
#include "../rcheevos/rc_compat.h"
#include "../rc_compat.h"
#include "md5.h"
@ -225,11 +225,11 @@ static void rc_cd_close_track(void* track_handle)
rc_hash_error("no hook registered for cdreader_close_track");
}
static uint32_t rc_cd_find_file_sector(void* track_handle, const char* path, unsigned* size)
static uint32_t rc_cd_find_file_sector(void* track_handle, const char* path, uint32_t* size)
{
uint8_t buffer[2048], *tmp;
int sector;
unsigned num_sectors = 0;
uint32_t num_sectors = 0;
size_t filename_length;
const char* slash;
@ -258,7 +258,7 @@ static uint32_t rc_cd_find_file_sector(void* track_handle, const char* path, uns
}
else
{
unsigned logical_block_size;
uint32_t logical_block_size;
/* find the cd information */
if (!rc_cd_read_sector(track_handle, rc_cd_first_track_sector(track_handle) + 16, buffer, 256))
@ -452,7 +452,7 @@ static int rc_hash_buffer(char hash[33], const uint8_t* buffer, size_t buffer_si
return rc_hash_finalize(&md5, hash);
}
static int rc_hash_cd_file(md5_state_t* md5, void* track_handle, uint32_t sector, const char* name, unsigned size, const char* description)
static int rc_hash_cd_file(md5_state_t* md5, void* track_handle, uint32_t sector, const char* name, uint32_t size, const char* description)
{
uint8_t buffer[2048];
size_t num_read;
@ -760,11 +760,11 @@ static int rc_hash_jaguar_cd(char hash[33], const char* path)
void* track_handle;
md5_state_t md5;
int byteswapped = 0;
unsigned size = 0;
unsigned offset = 0;
unsigned sector = 0;
unsigned remaining;
unsigned i;
uint32_t size = 0;
uint32_t offset = 0;
uint32_t sector = 0;
uint32_t remaining;
uint32_t i;
/* Jaguar CD header is in the first sector of the first data track OF THE SECOND SESSION.
* The first track must be an audio track, but may be a warning message or actual game audio */
@ -905,7 +905,7 @@ static int rc_hash_neogeo_cd(char hash[33], const char* path)
char buffer[1024], *ptr;
void* track_handle;
uint32_t sector;
unsigned size;
uint32_t size;
md5_state_t md5;
track_handle = rc_cd_open_track(path, 1);
@ -1091,7 +1091,7 @@ static int rc_hash_nintendo_ds(char hash[33], const char* path)
{
uint8_t header[512];
uint8_t* hash_buffer;
unsigned int hash_size, arm9_size, arm9_addr, arm7_size, arm7_addr, icon_addr;
uint32_t hash_size, arm9_size, arm9_addr, arm7_size, arm7_addr, icon_addr;
size_t num_read;
int64_t offset = 0;
md5_state_t md5;
@ -1332,8 +1332,8 @@ static int rc_hash_pce_track(char hash[33], void* track_handle)
{
uint8_t buffer[2048];
md5_state_t md5;
int sector, num_sectors;
unsigned size;
uint32_t sector, num_sectors;
uint32_t size;
/* the PC-Engine uses the second sector to specify boot information and program name.
* the string "PC Engine CD-ROM SYSTEM" should exist at 32 bytes into the sector
@ -1518,7 +1518,7 @@ static int rc_hash_dreamcast(char hash[33], const char* path)
uint8_t buffer[256] = "";
void* track_handle;
char exe_file[32] = "";
unsigned size;
uint32_t size;
uint32_t sector;
int result = 0;
md5_state_t md5;
@ -1612,10 +1612,10 @@ static int rc_hash_dreamcast(char hash[33], const char* path)
}
static int rc_hash_find_playstation_executable(void* track_handle, const char* boot_key, const char* cdrom_prefix,
char exe_name[], unsigned exe_name_size, unsigned* exe_size)
char exe_name[], uint32_t exe_name_size, uint32_t* exe_size)
{
uint8_t buffer[2048];
unsigned size;
uint32_t size;
char* ptr;
char* start;
const size_t boot_key_len = strlen(boot_key);
@ -1626,7 +1626,7 @@ static int rc_hash_find_playstation_executable(void* track_handle, const char* b
if (!sector)
return 0;
size = (unsigned)rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer) - 1);
size = (uint32_t)rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer) - 1);
buffer[size] = '\0';
sector = 0;
@ -1653,7 +1653,7 @@ static int rc_hash_find_playstation_executable(void* track_handle, const char* b
while (!isspace((unsigned char)*ptr) && *ptr != ';')
++ptr;
size = (unsigned)(ptr - start);
size = (uint32_t)(ptr - start);
if (size >= exe_name_size)
size = exe_name_size - 1;
@ -1685,7 +1685,7 @@ static int rc_hash_psx(char hash[33], const char* path)
char exe_name[64] = "";
void* track_handle;
uint32_t sector;
unsigned size;
uint32_t size;
int result = 0;
md5_state_t md5;
@ -1749,7 +1749,7 @@ static int rc_hash_ps2(char hash[33], const char* path)
char exe_name[64] = "";
void* track_handle;
uint32_t sector;
unsigned size;
uint32_t size;
int result = 0;
md5_state_t md5;
@ -1797,7 +1797,7 @@ static int rc_hash_psp(char hash[33], const char* path)
{
void* track_handle;
uint32_t sector;
unsigned size;
uint32_t size;
md5_state_t md5;
track_handle = rc_cd_open_track(path, 1);
@ -1868,6 +1868,21 @@ static int rc_hash_sega_cd(char hash[33], const char* path)
return rc_hash_buffer(hash, buffer, sizeof(buffer));
}
static int rc_hash_scv(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
/* if the file contains a header, ignore it */
/* https://gitlab.com/MaaaX-EmuSCV/libretro-emuscv/-/blob/master/readme.txt#L211 */
if (memcmp(buffer, "EmuSCV", 6) == 0)
{
rc_hash_verbose("Ignoring SCV header");
buffer += 32;
buffer_size -= 32;
}
return rc_hash_buffer(hash, buffer, buffer_size);
}
static int rc_hash_snes(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
/* if the file contains a header, ignore it */
@ -2028,6 +2043,9 @@ int rc_hash_generate_from_buffer(char hash[33], int console_id, const uint8_t* b
case RC_CONSOLE_PC_ENGINE: /* NOTE: does not support PCEngine CD */
return rc_hash_pce(hash, buffer, buffer_size);
case RC_CONSOLE_SUPER_CASSETTEVISION:
return rc_hash_scv(hash, buffer, buffer_size);
case RC_CONSOLE_SUPER_NINTENDO:
return rc_hash_snes(hash, buffer, buffer_size);
@ -2324,6 +2342,7 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
case RC_CONSOLE_ATARI_LYNX:
case RC_CONSOLE_NINTENDO:
case RC_CONSOLE_PC_ENGINE:
case RC_CONSOLE_SUPER_CASSETTEVISION:
case RC_CONSOLE_SUPER_NINTENDO:
/* additional logic whole-file hash - buffer then call rc_hash_generate_from_buffer */
return rc_hash_buffered_file(hash, console_id, path);
@ -2542,7 +2561,7 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
}
/* bin is associated with MegaDrive, Sega32X, Atari 2600, Watara Supervision, MegaDuck,
* Fairchild Channel F, Arcadia 2001, and Interton VC 4000.
* Fairchild Channel F, Arcadia 2001, Interton VC 4000, and Super Cassette Vision.
* Since they all use the same hashing algorithm, only specify one of them */
iterator->consoles[0] = RC_CONSOLE_MEGA_DRIVE;
}
@ -2572,9 +2591,10 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
iterator->consoles[1] = RC_CONSOLE_PLAYSTATION_2;
iterator->consoles[2] = RC_CONSOLE_DREAMCAST;
iterator->consoles[3] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */
iterator->consoles[4] = RC_CONSOLE_PC_ENGINE_CD;
iterator->consoles[5] = RC_CONSOLE_3DO;
iterator->consoles[6] = RC_CONSOLE_PCFX;
iterator->consoles[4] = RC_CONSOLE_PSP;
iterator->consoles[5] = RC_CONSOLE_PC_ENGINE_CD;
iterator->consoles[6] = RC_CONSOLE_3DO;
iterator->consoles[7] = RC_CONSOLE_PCFX;
need_path = 1;
}
else if (rc_path_compare_extension(ext, "col"))
@ -2589,6 +2609,10 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
{
iterator->consoles[0] = RC_CONSOLE_FAIRCHILD_CHANNEL_F;
}
else if (rc_path_compare_extension(ext, "cart"))
{
iterator->consoles[0] = RC_CONSOLE_SUPER_CASSETTEVISION;
}
break;
case 'd':

View File

@ -1,6 +1,6 @@
#include "rc_url.h"
#include "../rcheevos/rc_compat.h"
#include "../rc_compat.h"
#include "../rhash/md5.h"
#include <stdio.h>