Merge pull request #8501 from meleu/runtime_rcheevos_switch

add config option to choose between cheevos implementations
This commit is contained in:
Twinaphex 2019-04-20 15:23:51 +02:00 committed by GitHub
commit bca306a006
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 1844 additions and 3975 deletions

View File

@ -1710,76 +1710,72 @@ ifeq ($(HAVE_NETWORKING), 1)
# RetroAchievements
ifeq ($(HAVE_CHEEVOS), 1)
DEFINES += -DHAVE_CHEEVOS
DEFINES += -DHAVE_CHEEVOS \
-Ideps/rcheevos/include
ifeq ($(HAVE_NEW_CHEEVOS), 1)
DEFINES += -DHAVE_NEW_CHEEVOS \
-Ideps/rcheevos/include
OBJ += cheevos-new/cheevos.o \
cheevos-new/badges.o \
cheevos-new/fixup.o \
cheevos-new/parser.o \
cheevos-new/hash.o \
deps/rcheevos/src/rcheevos/trigger.o \
deps/rcheevos/src/rcheevos/condset.o \
deps/rcheevos/src/rcheevos/condition.o \
deps/rcheevos/src/rcheevos/operand.o \
deps/rcheevos/src/rcheevos/term.o \
deps/rcheevos/src/rcheevos/expression.o \
deps/rcheevos/src/rcheevos/value.o \
deps/rcheevos/src/rcheevos/lboard.o \
deps/rcheevos/src/rcheevos/alloc.o \
deps/rcheevos/src/rcheevos/format.o \
deps/rcheevos/src/rurl/url.o
OBJ += cheevos/cheevos.o \
cheevos/badges.o \
cheevos/var.o \
cheevos/cond.o \
cheevos-new/cheevos.o \
cheevos-new/fixup.o \
cheevos-new/parser.o \
cheevos-new/hash.o \
deps/rcheevos/src/rcheevos/trigger.o \
deps/rcheevos/src/rcheevos/condset.o \
deps/rcheevos/src/rcheevos/condition.o \
deps/rcheevos/src/rcheevos/operand.o \
deps/rcheevos/src/rcheevos/term.o \
deps/rcheevos/src/rcheevos/expression.o \
deps/rcheevos/src/rcheevos/value.o \
deps/rcheevos/src/rcheevos/lboard.o \
deps/rcheevos/src/rcheevos/alloc.o \
deps/rcheevos/src/rcheevos/format.o \
deps/rcheevos/src/rcheevos/memref.o \
deps/rcheevos/src/rcheevos/richpresence.o \
deps/rcheevos/src/rurl/url.o
ifeq ($(HAVE_LUA), 1)
DEFINES += -DHAVE_LUA \
-DLUA_32BITS \
-Ideps/lua/src
OBJ += deps/lua/src/lapi.o \
deps/lua/src/lcode.o \
deps/lua/src/lctype.o \
deps/lua/src/ldebug.o \
deps/lua/src/ldo.o \
deps/lua/src/ldump.o \
deps/lua/src/lfunc.o \
deps/lua/src/lgc.o \
deps/lua/src/llex.o \
deps/lua/src/lmem.o \
deps/lua/src/lobject.o \
deps/lua/src/lopcodes.o \
deps/lua/src/lparser.o \
deps/lua/src/lstate.o \
deps/lua/src/lstring.o \
deps/lua/src/ltable.o \
deps/lua/src/ltm.o \
deps/lua/src/lundump.o \
deps/lua/src/lvm.o \
deps/lua/src/lzio.o \
deps/lua/src/lauxlib.o \
deps/lua/src/lbaselib.o \
deps/lua/src/lbitlib.o \
deps/lua/src/lcorolib.o \
deps/lua/src/ldblib.o \
deps/lua/src/liolib.o \
deps/lua/src/lmathlib.o \
deps/lua/src/loslib.o \
deps/lua/src/lstrlib.o \
deps/lua/src/ltablib.o \
deps/lua/src/lutf8lib.o \
deps/lua/src/loadlib.o \
deps/lua/src/linit.o
else
DEFINES += -DRC_DISABLE_LUA
endif
# if not HAVE_NEW_CHEEVOS
ifeq ($(HAVE_LUA), 1)
DEFINES += -DHAVE_LUA \
-DLUA_32BITS \
-Ideps/lua/src
OBJ += deps/lua/src/lapi.o \
deps/lua/src/lcode.o \
deps/lua/src/lctype.o \
deps/lua/src/ldebug.o \
deps/lua/src/ldo.o \
deps/lua/src/ldump.o \
deps/lua/src/lfunc.o \
deps/lua/src/lgc.o \
deps/lua/src/llex.o \
deps/lua/src/lmem.o \
deps/lua/src/lobject.o \
deps/lua/src/lopcodes.o \
deps/lua/src/lparser.o \
deps/lua/src/lstate.o \
deps/lua/src/lstring.o \
deps/lua/src/ltable.o \
deps/lua/src/ltm.o \
deps/lua/src/lundump.o \
deps/lua/src/lvm.o \
deps/lua/src/lzio.o \
deps/lua/src/lauxlib.o \
deps/lua/src/lbaselib.o \
deps/lua/src/lbitlib.o \
deps/lua/src/lcorolib.o \
deps/lua/src/ldblib.o \
deps/lua/src/liolib.o \
deps/lua/src/lmathlib.o \
deps/lua/src/loslib.o \
deps/lua/src/lstrlib.o \
deps/lua/src/ltablib.o \
deps/lua/src/lutf8lib.o \
deps/lua/src/loadlib.o \
deps/lua/src/linit.o
else
OBJ += cheevos/cheevos.o \
cheevos/badges.o \
cheevos/var.o \
cheevos/cond.o
DEFINES += -DRC_DISABLE_LUA
endif
endif
ifeq ($(HAVE_DISCORD), 1)

File diff suppressed because it is too large Load Diff

View File

@ -27,49 +27,49 @@
RETRO_BEGIN_DECLS
typedef struct cheevos_ctx_desc
typedef struct rcheevos_ctx_desc
{
unsigned idx;
char *s;
size_t len;
} cheevos_ctx_desc_t;
} rcheevos_ctx_desc_t;
enum
{
CHEEVOS_ACTIVE_SOFTCORE = 1 << 0,
CHEEVOS_ACTIVE_HARDCORE = 1 << 1
RCHEEVOS_ACTIVE_SOFTCORE = 1 << 0,
RCHEEVOS_ACTIVE_HARDCORE = 1 << 1
};
bool cheevos_load(const void *data);
bool rcheevos_load(const void *data);
void cheevos_reset_game(void);
void rcheevos_reset_game(void);
void cheevos_populate_menu(void *data);
void rcheevos_populate_menu(void *data);
bool cheevos_get_description(cheevos_ctx_desc_t *desc);
bool rcheevos_get_description(rcheevos_ctx_desc_t *desc);
bool cheevos_apply_cheats(bool *data_bool);
bool rcheevos_apply_cheats(bool *data_bool);
bool cheevos_unload(void);
bool rcheevos_unload(void);
bool cheevos_toggle_hardcore_mode(void);
bool rcheevos_toggle_hardcore_mode(void);
void cheevos_test(void);
void rcheevos_test(void);
bool cheevos_set_cheats(void);
bool rcheevos_set_cheats(void);
void cheevos_set_support_cheevos(bool state);
void rcheevos_set_support_cheevos(bool state);
bool cheevos_get_support_cheevos(void);
bool rcheevos_get_support_cheevos(void);
int cheevos_get_console(void);
int rcheevos_get_console(void);
extern bool cheevos_loaded;
extern bool cheevos_hardcore_active;
extern bool cheevos_hardcore_paused;
extern bool cheevos_state_loaded_flag;
extern int cheats_are_enabled;
extern int cheats_were_enabled;
extern bool rcheevos_loaded;
extern bool rcheevos_hardcore_active;
extern bool rcheevos_hardcore_paused;
extern bool rcheevos_state_loaded_flag;
extern int rcheevos_cheats_are_enabled;
extern int rcheevos_cheats_were_enabled;
RETRO_END_DECLS

View File

@ -5,7 +5,7 @@
Released under the CC0: https://creativecommons.org/publicdomain/zero/1.0/
*/
/* Use at the beginning of the coroutine, you must have declared a variable coro_t* coro */
/* Use at the beginning of the coroutine, you must have declared a variable rcheevos_coro_t* coro */
#define CORO_ENTER() \
{ \
CORO_again: ; \
@ -67,7 +67,7 @@ Released under the CC0: https://creativecommons.org/publicdomain/zero/1.0/
return 0; \
} while ( 0 )
/* Add this macro to your coro_t structure containing the variables for the coroutine */
/* Add this macro to your rcheevos_coro_t structure containing the variables for the coroutine */
#define CORO_FIELDS \
int step, sp; \
int stack[ 8 ];

View File

@ -22,10 +22,10 @@
#include <rcheevos.h>
static int cheevos_cmpaddr(const void* e1, const void* e2)
static int rcheevos_cmpaddr(const void* e1, const void* e2)
{
const cheevos_fixup_t* f1 = (const cheevos_fixup_t*)e1;
const cheevos_fixup_t* f2 = (const cheevos_fixup_t*)e2;
const rcheevos_fixup_t* f1 = (const rcheevos_fixup_t*)e1;
const rcheevos_fixup_t* f2 = (const rcheevos_fixup_t*)e2;
if (f1->address < f2->address)
{
@ -41,7 +41,7 @@ static int cheevos_cmpaddr(const void* e1, const void* e2)
}
}
static size_t cheevos_var_reduce(size_t addr, size_t mask)
static size_t rcheevos_var_reduce(size_t addr, size_t mask)
{
while (mask)
{
@ -53,7 +53,7 @@ static size_t cheevos_var_reduce(size_t addr, size_t mask)
return addr;
}
static size_t cheevos_var_highest_bit(size_t n)
static size_t rcheevos_var_highest_bit(size_t n)
{
n |= n >> 1;
n |= n >> 2;
@ -64,33 +64,33 @@ static size_t cheevos_var_highest_bit(size_t n)
return n ^ (n >> 1);
}
void cheevos_fixup_init(cheevos_fixups_t* fixups)
void rcheevos_fixup_init(rcheevos_fixups_t* fixups)
{
fixups->elements = NULL;
fixups->capacity = fixups->count = 0;
fixups->dirty = false;
}
void cheevos_fixup_destroy(cheevos_fixups_t* fixups)
void rcheevos_fixup_destroy(rcheevos_fixups_t* fixups)
{
CHEEVOS_FREE(fixups->elements);
cheevos_fixup_init(fixups);
rcheevos_fixup_init(fixups);
}
const uint8_t* cheevos_fixup_find(cheevos_fixups_t* fixups, unsigned address, int console)
const uint8_t* rcheevos_fixup_find(rcheevos_fixups_t* fixups, unsigned address, int console)
{
cheevos_fixup_t key;
cheevos_fixup_t* found;
rcheevos_fixup_t key;
rcheevos_fixup_t* found;
const uint8_t* location;
if (fixups->dirty)
{
qsort(fixups->elements, fixups->count, sizeof(cheevos_fixup_t), cheevos_cmpaddr);
qsort(fixups->elements, fixups->count, sizeof(rcheevos_fixup_t), rcheevos_cmpaddr);
fixups->dirty = false;
}
key.address = address;
found = (cheevos_fixup_t*)bsearch(&key, fixups->elements, fixups->count, sizeof(cheevos_fixup_t), cheevos_cmpaddr);
found = (rcheevos_fixup_t*)bsearch(&key, fixups->elements, fixups->count, sizeof(rcheevos_fixup_t), rcheevos_cmpaddr);
if (found != NULL)
{
@ -100,8 +100,8 @@ const uint8_t* cheevos_fixup_find(cheevos_fixups_t* fixups, unsigned address, in
if (fixups->count == fixups->capacity)
{
unsigned new_capacity = fixups->capacity == 0 ? 16 : fixups->capacity * 2;
cheevos_fixup_t* new_elements = (cheevos_fixup_t*)
realloc(fixups->elements, new_capacity * sizeof(cheevos_fixup_t));
rcheevos_fixup_t* new_elements = (rcheevos_fixup_t*)
realloc(fixups->elements, new_capacity * sizeof(rcheevos_fixup_t));
if (new_elements == NULL)
{
@ -114,13 +114,13 @@ const uint8_t* cheevos_fixup_find(cheevos_fixups_t* fixups, unsigned address, in
fixups->elements[fixups->count].address = address;
fixups->elements[fixups->count++].location = location =
cheevos_patch_address(address, console);
rcheevos_patch_address(address, console);
fixups->dirty = true;
return location;
}
const uint8_t* cheevos_patch_address(unsigned address, int console)
const uint8_t* rcheevos_patch_address(unsigned address, int console)
{
rarch_system_info_t* system = runloop_get_system_info();
const void* pointer = NULL;
@ -130,7 +130,7 @@ const uint8_t* cheevos_patch_address(unsigned address, int console)
if (address >= 0x0800 && address < 0x2000)
{
/* Address in the mirrorred RAM, adjust to real RAM. */
CHEEVOS_LOG(CHEEVOS_TAG "NES memory address in mirrorred RAM %X, adjusted to %X\n", address, address & 0x07ff);
CHEEVOS_LOG(RCHEEVOS_TAG "NES memory address in mirrorred RAM %X, adjusted to %X\n", address, address & 0x07ff);
address &= 0x07ff;
}
}
@ -139,7 +139,7 @@ const uint8_t* cheevos_patch_address(unsigned address, int console)
if (address >= 0xe000 && address <= 0xfdff)
{
/* Address in the echo RAM, adjust to real RAM. */
CHEEVOS_LOG(CHEEVOS_TAG "GBC memory address in echo RAM %X, adjusted to %X\n", address, address - 0x2000);
CHEEVOS_LOG(RCHEEVOS_TAG "GBC memory address in echo RAM %X, adjusted to %X\n", address, address - 0x2000);
address -= 0x2000;
}
}
@ -156,20 +156,20 @@ const uint8_t* cheevos_patch_address(unsigned address, int console)
if (address < 0x8000)
{
/* Internal RAM. */
CHEEVOS_LOG(CHEEVOS_TAG "GBA memory address %X adjusted to %X\n", address, address + 0x3000000);
CHEEVOS_LOG(RCHEEVOS_TAG "GBA memory address %X adjusted to %X\n", address, address + 0x3000000);
address += 0x3000000;
}
else
{
/* Work RAM. */
CHEEVOS_LOG(CHEEVOS_TAG "GBA memory address %X adjusted to %X\n", address, address + 0x2000000 - 0x8000);
CHEEVOS_LOG(RCHEEVOS_TAG "GBA memory address %X adjusted to %X\n", address, address + 0x2000000 - 0x8000);
address += 0x2000000 - 0x8000;
}
}
else if (console == RC_CONSOLE_PC_ENGINE)
{
/* RAM. */
CHEEVOS_LOG(CHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x1f0000);
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x1f0000);
address += 0x1f0000;
}
else if (console == RC_CONSOLE_SUPER_NINTENDO)
@ -177,13 +177,13 @@ const uint8_t* cheevos_patch_address(unsigned address, int console)
if (address < 0x020000)
{
/* Work RAM. */
CHEEVOS_LOG(CHEEVOS_TAG "SNES memory address %X adjusted to %X\n", address, address + 0x7e0000);
CHEEVOS_LOG(RCHEEVOS_TAG "SNES memory address %X adjusted to %X\n", address, address + 0x7e0000);
address += 0x7e0000;
}
else
{
/* Save RAM. */
CHEEVOS_LOG(CHEEVOS_TAG "SNES memory address %X adjusted to %X\n", address, address + 0x006000 - 0x020000);
CHEEVOS_LOG(RCHEEVOS_TAG "SNES memory address %X adjusted to %X\n", address, address + 0x006000 - 0x020000);
address += 0x006000 - 0x020000;
}
}
@ -198,16 +198,16 @@ const uint8_t* cheevos_patch_address(unsigned address, int console)
unsigned addr = address;
pointer = desc->core.ptr;
address = (unsigned)cheevos_var_reduce(
address = (unsigned)rcheevos_var_reduce(
(addr - desc->core.start) & desc->disconnect_mask,
desc->core.disconnect);
if (address >= desc->core.len)
address -= cheevos_var_highest_bit(address);
address -= rcheevos_var_highest_bit(address);
address += desc->core.offset;
CHEEVOS_LOG(CHEEVOS_TAG "address %X set to descriptor %d at offset %X\n", addr, (int)((desc - system->mmaps.descriptors) + 1), address);
CHEEVOS_LOG(RCHEEVOS_TAG "address %X set to descriptor %d at offset %X\n", addr, (int)((desc - system->mmaps.descriptors) + 1), address);
break;
}
}

View File

@ -27,21 +27,21 @@ typedef struct
{
unsigned address;
const uint8_t* location;
} cheevos_fixup_t;
} rcheevos_fixup_t;
typedef struct
{
cheevos_fixup_t* elements;
rcheevos_fixup_t* elements;
unsigned capacity, count;
bool dirty;
} cheevos_fixups_t;
} rcheevos_fixups_t;
void cheevos_fixup_init(cheevos_fixups_t* fixups);
void cheevos_fixup_destroy(cheevos_fixups_t* fixups);
void rcheevos_fixup_init(rcheevos_fixups_t* fixups);
void rcheevos_fixup_destroy(rcheevos_fixups_t* fixups);
const uint8_t* cheevos_fixup_find(cheevos_fixups_t* fixups, unsigned address, int console);
const uint8_t* rcheevos_fixup_find(rcheevos_fixups_t* fixups, unsigned address, int console);
const uint8_t* cheevos_patch_address(unsigned address, int console);
const uint8_t* rcheevos_patch_address(unsigned address, int console);
RETRO_END_DECLS

View File

@ -1,6 +1,6 @@
#include "hash.h"
uint32_t cheevos_djb2(const char* str, size_t length)
uint32_t rcheevos_djb2(const char* str, size_t length)
{
const unsigned char* aux = (const unsigned char*)str;
uint32_t hash = 5381;

View File

@ -23,7 +23,7 @@
RETRO_BEGIN_DECLS
uint32_t cheevos_djb2(const char* str, size_t length);
uint32_t rcheevos_djb2(const char* str, size_t length);
RETRO_END_DECLS

View File

@ -38,21 +38,21 @@ typedef struct
int is_key;
const char* value;
size_t length;
} cheevos_getvalueud_t;
} rcheevos_getvalueud_t;
static int cheevos_getvalue_key(void* userdata,
static int rcheevos_getvalue_key(void* userdata,
const char* name, size_t length)
{
cheevos_getvalueud_t* ud = (cheevos_getvalueud_t*)userdata;
rcheevos_getvalueud_t* ud = (rcheevos_getvalueud_t*)userdata;
ud->is_key = cheevos_djb2(name, length) == ud->key_hash;
ud->is_key = rcheevos_djb2(name, length) == ud->key_hash;
return 0;
}
static int cheevos_getvalue_string(void* userdata,
static int rcheevos_getvalue_string(void* userdata,
const char* string, size_t length)
{
cheevos_getvalueud_t* ud = (cheevos_getvalueud_t*)userdata;
rcheevos_getvalueud_t* ud = (rcheevos_getvalueud_t*)userdata;
if (ud->is_key)
{
@ -64,9 +64,9 @@ static int cheevos_getvalue_string(void* userdata,
return 0;
}
static int cheevos_getvalue_boolean(void* userdata, int istrue)
static int rcheevos_getvalue_boolean(void* userdata, int istrue)
{
cheevos_getvalueud_t* ud = (cheevos_getvalueud_t*)userdata;
rcheevos_getvalueud_t* ud = (rcheevos_getvalueud_t*)userdata;
if (ud->is_key)
{
@ -87,9 +87,9 @@ static int cheevos_getvalue_boolean(void* userdata, int istrue)
return 0;
}
static int cheevos_getvalue_null(void* userdata)
static int rcheevos_getvalue_null(void* userdata)
{
cheevos_getvalueud_t* ud = (cheevos_getvalueud_t*)userdata;
rcheevos_getvalueud_t* ud = (rcheevos_getvalueud_t*)userdata;
if (ud->is_key )
{
@ -101,7 +101,7 @@ static int cheevos_getvalue_null(void* userdata)
return 0;
}
static int cheevos_get_value(const char* json, unsigned key_hash,
static int rcheevos_get_value(const char* json, unsigned key_hash,
char* value, size_t length)
{
static const jsonsax_handlers_t handlers =
@ -112,15 +112,15 @@ static int cheevos_get_value(const char* json, unsigned key_hash,
NULL,
NULL,
NULL,
cheevos_getvalue_key,
rcheevos_getvalue_key,
NULL,
cheevos_getvalue_string,
cheevos_getvalue_string, /* number */
cheevos_getvalue_boolean,
cheevos_getvalue_null
rcheevos_getvalue_string,
rcheevos_getvalue_string, /* number */
rcheevos_getvalue_boolean,
rcheevos_getvalue_null
};
cheevos_getvalueud_t ud;
rcheevos_getvalueud_t ud;
ud.key_hash = key_hash;
ud.is_key = 0;
@ -142,14 +142,14 @@ static int cheevos_get_value(const char* json, unsigned key_hash,
Returns the token of the error message
*****************************************************************************/
int cheevos_get_token(const char* json, char* token, size_t length)
int rcheevos_get_token(const char* json, char* token, size_t length)
{
cheevos_get_value(json, CHEEVOS_JSON_KEY_ERROR, token, length);
rcheevos_get_value(json, CHEEVOS_JSON_KEY_ERROR, token, length);
if (!string_is_empty(token))
return -1;
return cheevos_get_value(json, CHEEVOS_JSON_KEY_TOKEN, token, length);
return rcheevos_get_value(json, CHEEVOS_JSON_KEY_TOKEN, token, length);
}
/*****************************************************************************
@ -164,23 +164,23 @@ typedef struct
unsigned core_count;
unsigned unofficial_count;
unsigned lboard_count;
} cheevos_countud_t;
} rcheevos_countud_t;
static int cheevos_count_end_array(void* userdata)
static int rcheevos_count_end_array(void* userdata)
{
cheevos_countud_t* ud = (cheevos_countud_t*)userdata;
rcheevos_countud_t* ud = (rcheevos_countud_t*)userdata;
ud->in_cheevos = 0;
ud->in_lboards = 0;
return 0;
}
static int cheevos_count_key(void* userdata,
static int rcheevos_count_key(void* userdata,
const char* name, size_t length)
{
cheevos_countud_t* ud = (cheevos_countud_t*)userdata;
rcheevos_countud_t* ud = (rcheevos_countud_t*)userdata;
ud->field_hash = cheevos_djb2(name, length);
ud->field_hash = rcheevos_djb2(name, length);
if (ud->field_hash == CHEEVOS_JSON_KEY_ACHIEVEMENTS)
ud->in_cheevos = 1;
@ -190,10 +190,10 @@ static int cheevos_count_key(void* userdata,
return 0;
}
static int cheevos_count_number(void* userdata,
static int rcheevos_count_number(void* userdata,
const char* number, size_t length)
{
cheevos_countud_t* ud = (cheevos_countud_t*)userdata;
rcheevos_countud_t* ud = (rcheevos_countud_t*)userdata;
if (ud->in_cheevos && ud->field_hash == CHEEVOS_JSON_KEY_FLAGS)
{
@ -210,7 +210,7 @@ static int cheevos_count_number(void* userdata,
return 0;
}
static int cheevos_count_cheevos(const char* json,
static int rcheevos_count_cheevos(const char* json,
unsigned* core_count, unsigned* unofficial_count,
unsigned* lboard_count)
{
@ -221,17 +221,17 @@ static int cheevos_count_cheevos(const char* json,
NULL,
NULL,
NULL,
cheevos_count_end_array,
cheevos_count_key,
rcheevos_count_end_array,
rcheevos_count_key,
NULL,
NULL,
cheevos_count_number,
rcheevos_count_number,
NULL,
NULL
};
int res;
cheevos_countud_t ud;
rcheevos_countud_t ud;
ud.in_cheevos = 0;
ud.in_lboards = 0;
ud.core_count = 0;
@ -255,7 +255,7 @@ typedef struct
{
const char* string;
size_t length;
} cheevos_field_t;
} rcheevos_field_t;
typedef struct
{
@ -266,14 +266,14 @@ typedef struct
unsigned unofficial_count;
unsigned lboard_count;
cheevos_field_t* field;
cheevos_field_t id, memaddr, title, desc, points, author;
cheevos_field_t modified, created, badge, flags, format;
rcheevos_field_t* field;
rcheevos_field_t id, memaddr, title, desc, points, author;
rcheevos_field_t modified, created, badge, flags, format;
cheevos_rapatchdata_t* patchdata;
} cheevos_readud_t;
rcheevos_rapatchdata_t* patchdata;
} rcheevos_readud_t;
static const char* cheevos_dupstr(const cheevos_field_t* field)
static const char* rcheevos_dupstr(const rcheevos_field_t* field)
{
char* string = (char*)malloc(field->length + 1);
@ -285,9 +285,9 @@ static const char* cheevos_dupstr(const cheevos_field_t* field)
return string;
}
static int cheevos_new_cheevo(cheevos_readud_t* ud)
static int rcheevos_new_cheevo(rcheevos_readud_t* ud)
{
cheevos_racheevo_t* cheevo = NULL;
rcheevos_racheevo_t* cheevo = NULL;
unsigned flags = (unsigned)strtol(ud->flags.string, NULL, 10);
if (flags == 3)
@ -297,10 +297,10 @@ static int cheevos_new_cheevo(cheevos_readud_t* ud)
else
return 0;
cheevo->title = cheevos_dupstr(&ud->title);
cheevo->description = cheevos_dupstr(&ud->desc);
cheevo->badge = cheevos_dupstr(&ud->badge);
cheevo->memaddr = cheevos_dupstr(&ud->memaddr);
cheevo->title = rcheevos_dupstr(&ud->title);
cheevo->description = rcheevos_dupstr(&ud->desc);
cheevo->badge = rcheevos_dupstr(&ud->badge);
cheevo->memaddr = rcheevos_dupstr(&ud->memaddr);
cheevo->points = (unsigned)strtol(ud->points.string, NULL, 10);
cheevo->id = (unsigned)strtol(ud->id.string, NULL, 10);
@ -319,14 +319,14 @@ static int cheevos_new_cheevo(cheevos_readud_t* ud)
return 0;
}
static int cheevos_new_lboard(cheevos_readud_t* ud)
static int rcheevos_new_lboard(rcheevos_readud_t* ud)
{
cheevos_ralboard_t* lboard = ud->patchdata->lboards + ud->lboard_count++;
rcheevos_ralboard_t* lboard = ud->patchdata->lboards + ud->lboard_count++;
lboard->title = cheevos_dupstr(&ud->title);
lboard->description = cheevos_dupstr(&ud->desc);
lboard->format = cheevos_dupstr(&ud->format);
lboard->mem = cheevos_dupstr(&ud->memaddr);
lboard->title = rcheevos_dupstr(&ud->title);
lboard->description = rcheevos_dupstr(&ud->desc);
lboard->format = rcheevos_dupstr(&ud->format);
lboard->mem = rcheevos_dupstr(&ud->memaddr);
lboard->id = (unsigned)strtol(ud->id.string, NULL, 10);
if ( !lboard->title
@ -344,35 +344,35 @@ static int cheevos_new_lboard(cheevos_readud_t* ud)
return 0;
}
static int cheevos_read_end_object(void* userdata)
static int rcheevos_read_end_object(void* userdata)
{
cheevos_readud_t* ud = (cheevos_readud_t*)userdata;
rcheevos_readud_t* ud = (rcheevos_readud_t*)userdata;
if (ud->in_cheevos)
return cheevos_new_cheevo(ud);
return rcheevos_new_cheevo(ud);
if (ud->in_lboards)
return cheevos_new_lboard(ud);
return rcheevos_new_lboard(ud);
return 0;
}
static int cheevos_read_end_array(void* userdata)
static int rcheevos_read_end_array(void* userdata)
{
cheevos_readud_t* ud = (cheevos_readud_t*)userdata;
rcheevos_readud_t* ud = (rcheevos_readud_t*)userdata;
ud->in_cheevos = 0;
ud->in_lboards = 0;
return 0;
}
static int cheevos_read_key(void* userdata,
static int rcheevos_read_key(void* userdata,
const char* name, size_t length)
{
cheevos_readud_t* ud = (cheevos_readud_t*)userdata;
rcheevos_readud_t* ud = (rcheevos_readud_t*)userdata;
int common = ud->in_cheevos || ud->in_lboards;
uint32_t hash = cheevos_djb2(name, length);
uint32_t hash = rcheevos_djb2(name, length);
ud->field = NULL;
switch (hash)
@ -441,10 +441,10 @@ static int cheevos_read_key(void* userdata,
return 0;
}
static int cheevos_read_string(void* userdata,
static int rcheevos_read_string(void* userdata,
const char* string, size_t length)
{
cheevos_readud_t* ud = (cheevos_readud_t*)userdata;
rcheevos_readud_t* ud = (rcheevos_readud_t*)userdata;
if (ud->field)
{
@ -455,10 +455,10 @@ static int cheevos_read_string(void* userdata,
return 0;
}
static int cheevos_read_number(void* userdata,
static int rcheevos_read_number(void* userdata,
const char* number, size_t length)
{
cheevos_readud_t* ud = (cheevos_readud_t*)userdata;
rcheevos_readud_t* ud = (rcheevos_readud_t*)userdata;
if (ud->field)
{
@ -474,29 +474,29 @@ static int cheevos_read_number(void* userdata,
return 0;
}
int cheevos_get_patchdata(const char* json, cheevos_rapatchdata_t* patchdata)
int rcheevos_get_patchdata(const char* json, rcheevos_rapatchdata_t* patchdata)
{
static const jsonsax_handlers_t handlers =
{
NULL,
NULL,
NULL,
cheevos_read_end_object,
rcheevos_read_end_object,
NULL,
cheevos_read_end_array,
cheevos_read_key,
rcheevos_read_end_array,
rcheevos_read_key,
NULL,
cheevos_read_string,
cheevos_read_number,
rcheevos_read_string,
rcheevos_read_number,
NULL,
NULL
};
cheevos_readud_t ud;
rcheevos_readud_t ud;
int res;
/* Count the number of achievements in the JSON file. */
res = cheevos_count_cheevos(json, &patchdata->core_count,
res = rcheevos_count_cheevos(json, &patchdata->core_count,
&patchdata->unofficial_count, &patchdata->lboard_count);
if (res != JSONSAX_OK)
@ -504,14 +504,14 @@ int cheevos_get_patchdata(const char* json, cheevos_rapatchdata_t* patchdata)
/* Allocate the achievements. */
patchdata->core = (cheevos_racheevo_t*)
calloc(patchdata->core_count, sizeof(cheevos_racheevo_t));
patchdata->core = (rcheevos_racheevo_t*)
calloc(patchdata->core_count, sizeof(rcheevos_racheevo_t));
patchdata->unofficial = (cheevos_racheevo_t*)
calloc(patchdata->unofficial_count, sizeof(cheevos_racheevo_t));
patchdata->unofficial = (rcheevos_racheevo_t*)
calloc(patchdata->unofficial_count, sizeof(rcheevos_racheevo_t));
patchdata->lboards = (cheevos_ralboard_t*)
calloc(patchdata->lboard_count, sizeof(cheevos_ralboard_t));
patchdata->lboards = (rcheevos_ralboard_t*)
calloc(patchdata->lboard_count, sizeof(rcheevos_ralboard_t));
if (!patchdata->core ||
!patchdata->unofficial ||
@ -536,7 +536,7 @@ int cheevos_get_patchdata(const char* json, cheevos_rapatchdata_t* patchdata)
if (jsonsax_parse(json, &handlers, (void*)&ud) != JSONSAX_OK)
{
cheevos_free_patchdata(patchdata);
rcheevos_free_patchdata(patchdata);
return -1;
}
@ -547,11 +547,11 @@ int cheevos_get_patchdata(const char* json, cheevos_rapatchdata_t* patchdata)
Frees the patchdata
*****************************************************************************/
void cheevos_free_patchdata(cheevos_rapatchdata_t* patchdata)
void rcheevos_free_patchdata(rcheevos_rapatchdata_t* patchdata)
{
unsigned i = 0, count = 0;
const cheevos_racheevo_t* cheevo = NULL;
const cheevos_ralboard_t* lboard = NULL;
const rcheevos_racheevo_t* cheevo = NULL;
const rcheevos_ralboard_t* lboard = NULL;
cheevo = patchdata->core;
@ -603,22 +603,22 @@ Deactivates unlocked cheevos
typedef struct
{
int is_element;
cheevos_unlock_cb_t unlock_cb;
rcheevos_unlock_cb_t unlock_cb;
void* userdata;
} cheevos_deactivate_t;
} rcheevos_deactivate_t;
static int cheevos_deactivate_index(void* userdata, unsigned int index)
static int rcheevos_deactivate_index(void* userdata, unsigned int index)
{
cheevos_deactivate_t* ud = (cheevos_deactivate_t*)userdata;
rcheevos_deactivate_t* ud = (rcheevos_deactivate_t*)userdata;
ud->is_element = 1;
return 0;
}
static int cheevos_deactivate_number(void* userdata,
static int rcheevos_deactivate_number(void* userdata,
const char* number, size_t length)
{
cheevos_deactivate_t* ud = (cheevos_deactivate_t*)userdata;
rcheevos_deactivate_t* ud = (rcheevos_deactivate_t*)userdata;
unsigned id = 0;
if (ud->is_element)
@ -632,7 +632,7 @@ static int cheevos_deactivate_number(void* userdata,
return 0;
}
void cheevos_deactivate_unlocks(const char* json, cheevos_unlock_cb_t unlock_cb, void* userdata)
void rcheevos_deactivate_unlocks(const char* json, rcheevos_unlock_cb_t unlock_cb, void* userdata)
{
static const jsonsax_handlers_t handlers =
{
@ -643,14 +643,14 @@ void cheevos_deactivate_unlocks(const char* json, cheevos_unlock_cb_t unlock_cb,
NULL,
NULL,
NULL,
cheevos_deactivate_index,
rcheevos_deactivate_index,
NULL,
cheevos_deactivate_number,
rcheevos_deactivate_number,
NULL,
NULL
};
cheevos_deactivate_t ud;
rcheevos_deactivate_t ud;
ud.is_element = 0;
ud.unlock_cb = unlock_cb;
@ -667,7 +667,7 @@ unsigned chevos_get_gameid(const char* json)
{
char gameid[32];
if (cheevos_get_value(json, CHEEVOS_JSON_KEY_GAMEID, gameid, sizeof(gameid)) != 0)
if (rcheevos_get_value(json, CHEEVOS_JSON_KEY_GAMEID, gameid, sizeof(gameid)) != 0)
return 0;
return (unsigned)strtol(gameid, NULL, 10);

View File

@ -31,7 +31,7 @@ typedef struct {
const char* memaddr;
unsigned points;
unsigned id;
} cheevos_racheevo_t;
} rcheevos_racheevo_t;
typedef struct {
const char* title;
@ -39,28 +39,28 @@ typedef struct {
const char* format;
const char* mem;
unsigned id;
} cheevos_ralboard_t;
} rcheevos_ralboard_t;
typedef struct {
unsigned console_id;
cheevos_racheevo_t* core;
cheevos_racheevo_t* unofficial;
cheevos_ralboard_t* lboards;
rcheevos_racheevo_t* core;
rcheevos_racheevo_t* unofficial;
rcheevos_ralboard_t* lboards;
unsigned core_count;
unsigned unofficial_count;
unsigned lboard_count;
} cheevos_rapatchdata_t;
} rcheevos_rapatchdata_t;
typedef void (*cheevos_unlock_cb_t)(unsigned id, void* userdata);
typedef void (*rcheevos_unlock_cb_t)(unsigned id, void* userdata);
int cheevos_get_token(const char* json, char* token, size_t length);
int rcheevos_get_token(const char* json, char* token, size_t length);
int cheevos_get_patchdata(const char* json, cheevos_rapatchdata_t* patchdata);
void cheevos_free_patchdata(cheevos_rapatchdata_t* patchdata);
int rcheevos_get_patchdata(const char* json, rcheevos_rapatchdata_t* patchdata);
void rcheevos_free_patchdata(rcheevos_rapatchdata_t* patchdata);
void cheevos_deactivate_unlocks(const char* json, cheevos_unlock_cb_t unlock_cb, void* userdata);
void rcheevos_deactivate_unlocks(const char* json, rcheevos_unlock_cb_t unlock_cb, void* userdata);
unsigned chevos_get_gameid(const char* json);

View File

@ -25,13 +25,13 @@ Setup - mainly for debugging
*****************************************************************************/
/* Define this macro to get extra-verbose log for cheevos. */
#undef CHEEVOS_VERBOSE
#define CHEEVOS_VERBOSE
/*****************************************************************************
End of setup
*****************************************************************************/
#define CHEEVOS_TAG "[CHEEVOS]: "
#define RCHEEVOS_TAG "[RCHEEVOS]: "
#define CHEEVOS_FREE(p) do { void* q = (void*)p; if (q != NULL) free(q); } while (0)
#ifdef CHEEVOS_VERBOSE
@ -41,10 +41,10 @@ End of setup
#else
#define CHEEVOS_LOG cheevos_log
#define CHEEVOS_LOG rcheevos_log
#define CHEEVOS_ERR RARCH_ERR
void cheevos_log(const char *fmt, ...);
void rcheevos_log(const char *fmt, ...);
#endif

View File

@ -16,10 +16,6 @@
#ifndef __RARCH_CHEEVOS_OLD_BADGE_H
#define __RARCH_CHEEVOS_OLD_BADGE_H
#ifdef HAVE_NEW_CHEEVOS
#include "../cheevos-new/badges.h"
#else
#include "../menu/menu_driver.h"
#include <retro_common_api.h>
@ -46,5 +42,3 @@ static badges_ctx_t new_badges_ctx;
RETRO_END_DECLS
#endif
#endif

View File

@ -1862,8 +1862,6 @@ static void cheevos_test_leaderboards(void)
if (value != lboard->last_value)
{
CHEEVOS_LOG("[CHEEVOS]: value lboard %s %u\n",
lboard->title, value);
lboard->last_value = value;
}

View File

@ -16,10 +16,6 @@
#ifndef __RARCH_CHEEVOS_OLD_H
#define __RARCH_CHEEVOS_OLD_H
#ifdef HAVE_NEW_CHEEVOS
#include "../cheevos-new/cheevos.h"
#else
#include <stdint.h>
#include <stdlib.h>
@ -34,7 +30,7 @@ Setup - mainly for debugging
*****************************************************************************/
/* Define this macro to get extra-verbose log for cheevos. */
#undef CHEEVOS_VERBOSE
#define CHEEVOS_VERBOSE
/*****************************************************************************
End of setup
@ -166,6 +162,4 @@ extern int cheats_were_enabled;
RETRO_END_DECLS
#endif
#endif /* __RARCH_CHEEVOS_H */

114
command.c
View File

@ -41,11 +41,9 @@
#ifdef HAVE_CHEEVOS
#include "cheevos/cheevos.h"
#ifdef HAVE_NEW_CHEEVOS
#include "cheevos-new/fixup.h"
#else
#include "cheevos/var.h"
#endif
#include "cheevos-new/cheevos.h" /* RCHEEVOS TODO: remove lines */
#include "cheevos-new/fixup.h"
#endif
#ifdef HAVE_DISCORD
@ -279,9 +277,10 @@ bool command_set_shader(const char *arg)
#define SMY_CMD_STR "READ_CORE_RAM"
static bool command_read_ram(const char *arg)
{
#if !defined(HAVE_NEW_CHEEVOS)
/* RCHEEVOS TODO: remove settings init and test */
settings_t *settings = config_get_ptr();
cheevos_var_t var;
#endif
unsigned i;
char *reply = NULL;
const uint8_t *data = NULL;
@ -297,13 +296,18 @@ static bool command_read_ram(const char *arg)
reply[0] = '\0';
reply_at = reply + snprintf(reply, alloc_size - 1, SMY_CMD_STR " %x", addr);
#if defined(HAVE_NEW_CHEEVOS)
data = cheevos_patch_address(addr, cheevos_get_console());
#else
var.value = addr;
cheevos_var_patch_addr(&var, cheevos_get_console());
data = cheevos_var_get_memory(&var);
#endif
/* RCHEEVOS TODO: remove if condition below */
if (settings->bools.cheevos_rcheevos_enable)
{
data = rcheevos_patch_address(addr, rcheevos_get_console());
}
/* RCHEEVOS TODO: remove whole else block below */
else
{
var.value = addr;
cheevos_var_patch_addr(&var, cheevos_get_console());
data = cheevos_var_get_memory(&var);
}
if (data)
{
@ -324,19 +328,28 @@ static bool command_read_ram(const char *arg)
static bool command_write_ram(const char *arg)
{
unsigned nbytes = 0;
#if defined(HAVE_NEW_CHEEVOS)
unsigned int addr = strtoul(arg, (char**)&arg, 16);
uint8_t *data = (uint8_t *)cheevos_patch_address(addr, cheevos_get_console());
#else
cheevos_var_t var;
uint8_t *data = NULL;
unsigned nbytes = 0;
uint8_t *data = NULL;
unsigned int addr = 0;
var.value = strtoul(arg, (char**)&arg, 16);
cheevos_var_patch_addr(&var, cheevos_get_console());
/* RCHEEVOS TODO: remove settings init and test */
settings_t *settings = config_get_ptr();
data = cheevos_var_get_memory(&var);
#endif
if (settings->bools.cheevos_rcheevos_enable)
{
addr = strtoul(arg, (char**)&arg, 16);
data = (uint8_t *)rcheevos_patch_address(addr, rcheevos_get_console());
}
/* RCHEEVOS TODO: remove the whole else block below */
else
{
cheevos_var_t var;
var.value = strtoul(arg, (char**)&arg, 16);
cheevos_var_patch_addr(&var, cheevos_get_console());
data = cheevos_var_get_memory(&var);
}
if (data)
{
@ -1095,7 +1108,9 @@ static void command_event_init_controllers(void)
static void command_event_deinit_core(bool reinit)
{
#ifdef HAVE_CHEEVOS
cheevos_unload();
/* RCHEEVOS TODO: remove settings init and test */
settings_t *settings = config_get_ptr();
settings->bools.cheevos_rcheevos_enable ? rcheevos_unload() : cheevos_unload();
#endif
RARCH_LOG("Unloading game..\n");
@ -1150,7 +1165,8 @@ static void command_event_load_auto_state(void)
#endif
#ifdef HAVE_CHEEVOS
if (cheevos_hardcore_active)
/* RCHEEVOS TODO: remove OR below */
if (cheevos_hardcore_active || rcheevos_hardcore_active)
goto error;
#endif
@ -1401,7 +1417,8 @@ static bool command_event_save_auto_state(void)
goto error;
#ifdef HAVE_CHEEVOS
if (cheevos_hardcore_active)
/* RCHEEVOS TODO: remove OR below */
if (cheevos_hardcore_active || rcheevos_hardcore_active)
goto error;
#endif
@ -1701,7 +1718,8 @@ static bool command_event_main_state(unsigned cmd)
if (content_load_state(state_path, false, false))
{
#ifdef HAVE_CHEEVOS
cheevos_state_loaded_flag = true;
/* RCHEEVOS TODO: remove duplication below */
rcheevos_state_loaded_flag = cheevos_state_loaded_flag = true;
#endif
ret = true;
#ifdef HAVE_NETWORKING
@ -1848,7 +1866,8 @@ bool command_event(enum event_command cmd, void *data)
return false;
#ifdef HAVE_CHEEVOS
if (cheevos_hardcore_active)
/* RCHEEVOS TODO: remove OR below */
if (cheevos_hardcore_active || rcheevos_hardcore_active)
return false;
#endif
if (!command_event_main_state(cmd))
@ -1878,29 +1897,34 @@ bool command_event(enum event_command cmd, void *data)
command_event_init_controllers();
break;
case CMD_EVENT_RESET:
/* RCHEEVOS TODO: remove starting block bracket, settings init and tests */
{
#ifdef HAVE_CHEEVOS
cheevos_state_loaded_flag = false;
cheevos_hardcore_paused = false;
settings_t *settings = config_get_ptr();
rcheevos_state_loaded_flag = cheevos_state_loaded_flag = false;
rcheevos_hardcore_paused = cheevos_hardcore_paused = false;
#endif
RARCH_LOG("%s.\n", msg_hash_to_str(MSG_RESET));
runloop_msg_queue_push(msg_hash_to_str(MSG_RESET), 1, 120, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
RARCH_LOG("%s.\n", msg_hash_to_str(MSG_RESET));
runloop_msg_queue_push(msg_hash_to_str(MSG_RESET), 1, 120, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
#ifdef HAVE_CHEEVOS
cheevos_set_cheats();
settings->bools.cheevos_rcheevos_enable ? rcheevos_set_cheats() : cheevos_set_cheats();
#endif
core_reset();
core_reset();
#ifdef HAVE_CHEEVOS
cheevos_reset_game();
settings->bools.cheevos_rcheevos_enable ? rcheevos_reset_game() : cheevos_reset_game();
#endif
#if HAVE_NETWORKING
netplay_driver_ctl(RARCH_NETPLAY_CTL_RESET, NULL);
netplay_driver_ctl(RARCH_NETPLAY_CTL_RESET, NULL);
#endif
return false;
return false;
}
case CMD_EVENT_SAVE_STATE:
{
settings_t *settings = config_get_ptr();
#ifdef HAVE_CHEEVOS
if (cheevos_hardcore_active)
/* RCHEEVOS TODO: remove OR below */
if (cheevos_hardcore_active || rcheevos_hardcore_active)
return false;
#endif
@ -1982,7 +2006,11 @@ bool command_event(enum event_command cmd, void *data)
break;
case CMD_EVENT_CHEEVOS_HARDCORE_MODE_TOGGLE:
#ifdef HAVE_CHEEVOS
cheevos_toggle_hardcore_mode();
/* RCHEEVOS TODO: remove starting block bracket, settings init and test */
{
settings_t *settings = config_get_ptr();
settings->bools.cheevos_rcheevos_enable ? rcheevos_toggle_hardcore_mode() : cheevos_toggle_hardcore_mode();
}
#endif
break;
/* this fallthrough is on purpose, it should do
@ -2023,7 +2051,8 @@ bool command_event(enum event_command cmd, void *data)
break;
case CMD_EVENT_REWIND_DEINIT:
#ifdef HAVE_CHEEVOS
if (cheevos_hardcore_active)
/* RCHEEVOS TODO: remove OR below */
if (cheevos_hardcore_active || rcheevos_hardcore_active)
return false;
#endif
state_manager_event_deinit();
@ -2032,7 +2061,8 @@ bool command_event(enum event_command cmd, void *data)
{
settings_t *settings = config_get_ptr();
#ifdef HAVE_CHEEVOS
if (cheevos_hardcore_active)
/* RCHEEVOS TODO: remove OR below */
if (cheevos_hardcore_active || rcheevos_hardcore_active)
return false;
#endif
if (settings->bools.rewind_enable)

View File

@ -1526,6 +1526,8 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("cheevos_leaderboards_enable", &settings->bools.cheevos_leaderboards_enable, true, false, false);
SETTING_BOOL("cheevos_verbose_enable", &settings->bools.cheevos_verbose_enable, true, false, false);
SETTING_BOOL("cheevos_auto_screenshot", &settings->bools.cheevos_auto_screenshot, true, false, false);
SETTING_BOOL("cheevos_rcheevos_enable", &settings->bools.cheevos_rcheevos_enable, true, false, false);
/* RCHEEVOS TODO: remove line above */
#ifdef HAVE_XMB
SETTING_BOOL("cheevos_badges_enable", &settings->bools.cheevos_badges_enable, true, false, false);
#endif

View File

@ -240,6 +240,7 @@ typedef struct settings
bool cheevos_badges_enable;
bool cheevos_verbose_enable;
bool cheevos_auto_screenshot;
bool cheevos_rcheevos_enable; /* RCHEEVOS TODO: remove line */
/* Camera */
bool camera_allow;

View File

@ -29,7 +29,9 @@ enum {
RC_MISSING_CANCEL = -14,
RC_MISSING_SUBMIT = -15,
RC_MISSING_VALUE = -16,
RC_INVALID_LBOARD_FIELD = -17
RC_INVALID_LBOARD_FIELD = -17,
RC_MISSING_DISPLAY_STRING = -18,
RC_OUT_OF_MEMORY = -19
};
/*****************************************************************************\
@ -82,51 +84,74 @@ enum {
typedef unsigned (*rc_peek_t)(unsigned address, unsigned num_bytes, void* ud);
/*****************************************************************************\
| Operands |
| Memory References |
\*****************************************************************************/
/* Sizes. */
enum {
RC_OPERAND_BIT_0,
RC_OPERAND_BIT_1,
RC_OPERAND_BIT_2,
RC_OPERAND_BIT_3,
RC_OPERAND_BIT_4,
RC_OPERAND_BIT_5,
RC_OPERAND_BIT_6,
RC_OPERAND_BIT_7,
RC_OPERAND_LOW,
RC_OPERAND_HIGH,
RC_OPERAND_8_BITS,
RC_OPERAND_16_BITS,
RC_OPERAND_24_BITS,
RC_OPERAND_32_BITS
RC_MEMSIZE_BIT_0,
RC_MEMSIZE_BIT_1,
RC_MEMSIZE_BIT_2,
RC_MEMSIZE_BIT_3,
RC_MEMSIZE_BIT_4,
RC_MEMSIZE_BIT_5,
RC_MEMSIZE_BIT_6,
RC_MEMSIZE_BIT_7,
RC_MEMSIZE_LOW,
RC_MEMSIZE_HIGH,
RC_MEMSIZE_8_BITS,
RC_MEMSIZE_16_BITS,
RC_MEMSIZE_24_BITS,
RC_MEMSIZE_32_BITS
};
typedef struct {
/* The memory address of this variable. */
unsigned address;
/* The size of the variable. */
char size;
/* True if the value is in BCD. */
char is_bcd;
} rc_memref_t;
typedef struct rc_memref_value_t rc_memref_value_t;
struct rc_memref_value_t {
/* The value of this memory reference. */
unsigned value;
/* The previous value of this memory reference. */
unsigned previous;
/* The last differing value of this memory reference. */
unsigned prior;
/* The referenced memory */
rc_memref_t memref;
/* The next memory reference in the chain */
rc_memref_value_t* next;
};
/*****************************************************************************\
| Operands |
\*****************************************************************************/
/* types */
enum {
RC_OPERAND_ADDRESS, /* Compare to the value of a live address in RAM. */
RC_OPERAND_DELTA, /* The value last known at this address. */
RC_OPERAND_CONST, /* A 32-bit unsigned integer. */
RC_OPERAND_FP, /* A floating point value. */
RC_OPERAND_LUA /* A Lua function that provides the value. */
RC_OPERAND_LUA, /* A Lua function that provides the value. */
RC_OPERAND_PRIOR /* The last differing value at this address. */
};
typedef struct {
union {
/* A value read from memory. */
struct {
/* The memory address or constant value of this variable. */
unsigned value;
/* The previous memory contents if RC_OPERAND_DELTA. */
unsigned previous;
rc_memref_value_t* memref;
/* The size of the variable. */
char size;
/* True if the value is in BCD. */
char is_bcd;
/* The type of the variable. */
};
/* A value. */
unsigned value;
/* A floating point value. */
double fp_value;
@ -150,7 +175,8 @@ enum {
RC_CONDITION_RESET_IF,
RC_CONDITION_ADD_SOURCE,
RC_CONDITION_SUB_SOURCE,
RC_CONDITION_ADD_HITS
RC_CONDITION_ADD_HITS,
RC_CONDITION_AND_NEXT
};
/* operators */
@ -166,9 +192,6 @@ enum {
typedef struct rc_condition_t rc_condition_t;
struct rc_condition_t {
/* The next condition in the chain. */
rc_condition_t* next;
/* The condition's operands. */
rc_operand_t operand1;
rc_operand_t operand2;
@ -178,6 +201,9 @@ struct rc_condition_t {
/* Number of hits so far. */
unsigned current_hits;
/* The next condition in the chain. */
rc_condition_t* next;
/**
* Set if the condition needs to processed as part of the "check if paused"
* pass
@ -217,6 +243,9 @@ typedef struct {
/* The list of sub condition sets in this test. */
rc_condset_t* alternative;
/* The memory references required by the trigger. */
rc_memref_value_t* memrefs;
}
rc_trigger_t;
@ -257,6 +286,9 @@ struct rc_expression_t {
typedef struct {
/* The list of expression to evaluate. */
rc_expression_t* expressions;
/* The memory references required by the value. */
rc_memref_value_t* memrefs;
}
rc_value_t;
@ -283,6 +315,7 @@ typedef struct {
rc_trigger_t cancel;
rc_value_t value;
rc_value_t* progress;
rc_memref_value_t* memrefs;
char started;
char submitted;
@ -300,7 +333,7 @@ void rc_reset_lboard(rc_lboard_t* lboard);
/* Supported formats. */
enum {
RC_FORMAT_FRAMES = 0,
RC_FORMAT_FRAMES,
RC_FORMAT_SECONDS,
RC_FORMAT_CENTISECS,
RC_FORMAT_SCORE,
@ -309,7 +342,57 @@ enum {
};
int rc_parse_format(const char* format_str);
void rc_format_value(char* buffer, int size, unsigned value, int format);
int rc_format_value(char* buffer, int size, unsigned value, int format);
/*****************************************************************************\
| Rich Presence |
\*****************************************************************************/
typedef struct rc_richpresence_lookup_item_t rc_richpresence_lookup_item_t;
struct rc_richpresence_lookup_item_t {
unsigned value;
rc_richpresence_lookup_item_t* next_item;
const char* label;
};
typedef struct rc_richpresence_lookup_t rc_richpresence_lookup_t;
struct rc_richpresence_lookup_t {
rc_richpresence_lookup_item_t* first_item;
rc_richpresence_lookup_t* next;
const char* name;
unsigned short format;
};
typedef struct rc_richpresence_display_part_t rc_richpresence_display_part_t;
struct rc_richpresence_display_part_t {
rc_richpresence_display_part_t* next;
const char* text;
rc_richpresence_lookup_item_t* first_lookup_item;
rc_value_t value;
unsigned short display_type;
};
typedef struct rc_richpresence_display_t rc_richpresence_display_t;
struct rc_richpresence_display_t {
rc_trigger_t trigger;
rc_richpresence_display_t* next;
rc_richpresence_display_part_t* display;
};
typedef struct {
rc_richpresence_display_t* first_display;
rc_richpresence_lookup_t* first_lookup;
rc_memref_value_t* memrefs;
}
rc_richpresence_t;
int rc_richpresence_size(const char* script);
rc_richpresence_t* rc_parse_richpresence(void* buffer, const char* script, lua_State* L, int funcs_ndx);
int rc_evaluate_richpresence(rc_richpresence_t* richpresence, char* buffer, unsigned buffersize, rc_peek_t peek, void* peek_ud, lua_State* L);
#ifdef __cplusplus
}

View File

@ -1,5 +1,8 @@
#include "internal.h"
#include <stdlib.h>
#include <string.h>
void* rc_alloc(void* pointer, int* offset, int size, int alignment, rc_scratch_t* scratch) {
void* ptr;
@ -8,10 +11,43 @@ void* rc_alloc(void* pointer, int* offset, int size, int alignment, rc_scratch_t
if (pointer != 0) {
ptr = (void*)((char*)pointer + *offset);
}
else if (scratch != 0) {
ptr = &scratch->obj;
}
else {
ptr = scratch;
ptr = 0;
}
*offset += size;
return ptr;
}
char* rc_alloc_str(rc_parse_state_t* parse, const char* text, int length) {
char* ptr;
ptr = (char*)rc_alloc(parse->buffer, &parse->offset, length + 1, RC_ALIGNOF(char), 0);
if (ptr) {
memcpy(ptr, text, length);
ptr[length] = '\0';
}
return ptr;
}
void rc_init_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, int funcs_ndx)
{
parse->offset = 0;
parse->L = L;
parse->funcs_ndx = funcs_ndx;
parse->buffer = buffer;
parse->scratch.memref = parse->scratch.memref_buffer;
parse->scratch.memref_size = sizeof(parse->scratch.memref_buffer) / sizeof(parse->scratch.memref_buffer[0]);
parse->scratch.memref_count = 0;
parse->first_memref = 0;
}
void rc_destroy_parse_state(rc_parse_state_t* parse)
{
if (parse->scratch.memref != parse->scratch.memref_buffer)
free(parse->scratch.memref);
}

View File

@ -2,13 +2,13 @@
#include <stdlib.h>
rc_condition_t* rc_parse_condition(int* ret, void* buffer, rc_scratch_t* scratch, const char** memaddr, lua_State* L, int funcs_ndx) {
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse) {
rc_condition_t* self;
const char* aux;
int ret2;
aux = *memaddr;
self = RC_ALLOC(rc_condition_t, buffer, ret, scratch);
self = RC_ALLOC(rc_condition_t, parse);
self->current_hits = 0;
if (*aux != 0 && aux[1] == ':') {
@ -18,7 +18,8 @@ rc_condition_t* rc_parse_condition(int* ret, void* buffer, rc_scratch_t* scratch
case 'a': case 'A': self->type = RC_CONDITION_ADD_SOURCE; break;
case 'b': case 'B': self->type = RC_CONDITION_SUB_SOURCE; break;
case 'c': case 'C': self->type = RC_CONDITION_ADD_HITS; break;
default: *ret = RC_INVALID_CONDITION_TYPE; return 0;
case 'n': case 'N': self->type = RC_CONDITION_AND_NEXT; break;
default: parse->offset = RC_INVALID_CONDITION_TYPE; return 0;
}
aux += 2;
@ -27,10 +28,10 @@ rc_condition_t* rc_parse_condition(int* ret, void* buffer, rc_scratch_t* scratch
self->type = RC_CONDITION_STANDARD;
}
ret2 = rc_parse_operand(&self->operand1, &aux, 1, L, funcs_ndx);
ret2 = rc_parse_operand(&self->operand1, &aux, 1, parse);
if (ret2 < 0) {
*ret = ret2;
parse->offset = ret2;
return 0;
}
@ -44,7 +45,7 @@ rc_condition_t* rc_parse_condition(int* ret, void* buffer, rc_scratch_t* scratch
if (*aux++ != '=') {
/* fall through */
default:
*ret = RC_INVALID_OPERATOR;
parse->offset = RC_INVALID_OPERATOR;
return 0;
}
@ -72,10 +73,10 @@ rc_condition_t* rc_parse_condition(int* ret, void* buffer, rc_scratch_t* scratch
break;
}
ret2 = rc_parse_operand(&self->operand2, &aux, 1, L, funcs_ndx);
ret2 = rc_parse_operand(&self->operand2, &aux, 1, parse);
if (ret2 < 0) {
*ret = ret2;
parse->offset = ret2;
return 0;
}
@ -84,7 +85,7 @@ rc_condition_t* rc_parse_condition(int* ret, void* buffer, rc_scratch_t* scratch
self->required_hits = (unsigned)strtoul(++aux, &end, 10);
if (end == aux || *end != ')') {
*ret = RC_INVALID_REQUIRED_HITS;
parse->offset = RC_INVALID_REQUIRED_HITS;
return 0;
}
@ -95,7 +96,7 @@ rc_condition_t* rc_parse_condition(int* ret, void* buffer, rc_scratch_t* scratch
self->required_hits = (unsigned)strtoul(++aux, &end, 10);
if (end == aux || *end != '.') {
*ret = RC_INVALID_REQUIRED_HITS;
parse->offset = RC_INVALID_REQUIRED_HITS;
return 0;
}

View File

@ -13,6 +13,7 @@ static void rc_update_condition_pause(rc_condition_t* condition, int* in_pause)
case RC_CONDITION_ADD_SOURCE:
case RC_CONDITION_SUB_SOURCE:
case RC_CONDITION_ADD_HITS:
case RC_CONDITION_AND_NEXT:
condition->pause = *in_pause;
break;
@ -22,19 +23,25 @@ static void rc_update_condition_pause(rc_condition_t* condition, int* in_pause)
}
}
rc_condset_t* rc_parse_condset(int* ret, void* buffer, rc_scratch_t* scratch, const char** memaddr, lua_State* L, int funcs_ndx) {
rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse) {
rc_condset_t* self;
rc_condition_t** next;
int in_pause;
self = RC_ALLOC(rc_condset_t, buffer, ret, scratch);
self = RC_ALLOC(rc_condset_t, parse);
self->has_pause = 0;
next = &self->conditions;
for (;;) {
*next = rc_parse_condition(ret, buffer, scratch, memaddr, L, funcs_ndx);
if (**memaddr == 'S' || **memaddr == 's' || !**memaddr) {
/* empty group - editor allows it, so we have to support it */
*next = 0;
return self;
}
if (*ret < 0) {
for (;;) {
*next = rc_parse_condition(memaddr, parse);
if (parse->offset < 0) {
return 0;
}
@ -51,7 +58,7 @@ rc_condset_t* rc_parse_condset(int* ret, void* buffer, rc_scratch_t* scratch, co
*next = 0;
if (buffer != 0) {
if (parse->buffer != 0) {
in_pause = 0;
rc_update_condition_pause(self->conditions, &in_pause);
}
@ -61,10 +68,11 @@ rc_condset_t* rc_parse_condset(int* ret, void* buffer, rc_scratch_t* scratch, co
static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, int* reset, rc_peek_t peek, void* ud, lua_State* L) {
rc_condition_t* condition;
int set_valid, cond_valid;
int set_valid, cond_valid, prev_cond;
unsigned add_buffer, add_hits;
set_valid = 1;
prev_cond = 1;
add_buffer = add_hits = 0;
for (condition = self->conditions; condition != 0; condition = condition->next) {
@ -88,13 +96,23 @@ static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, in
}
}
add_buffer = 0;
add_hits += condition->current_hits;
continue;
case RC_CONDITION_AND_NEXT:
prev_cond &= rc_test_condition(condition, add_buffer, peek, ud, L);
add_buffer = 0;
continue;
}
/* always evaluate the condition to ensure delta values get tracked correctly */
cond_valid = rc_test_condition(condition, add_buffer, peek, ud, L);
/* merge AndNext value and reset it for the next condition */
cond_valid &= prev_cond;
prev_cond = 1;
/* if the condition has a target hit count that has already been met, it's automatically true, even if not currently true. */
if (condition->required_hits != 0 && (condition->current_hits + add_hits) >= condition->required_hits) {
cond_valid = 1;
@ -111,6 +129,7 @@ static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, in
}
}
/* reset AddHits and AddSource/SubSource values */
add_buffer = add_hits = 0;
switch (condition->type) {
@ -141,7 +160,7 @@ static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, in
}
break;
default:
set_valid &= cond_valid;
break;

View File

@ -1,16 +1,16 @@
#include "internal.h"
rc_expression_t* rc_parse_expression(int* ret, void* buffer, rc_scratch_t* scratch, const char** memaddr, lua_State* L, int funcs_ndx) {
rc_expression_t* rc_parse_expression(const char** memaddr, rc_parse_state_t* parse) {
rc_expression_t* self;
rc_term_t** next;
self = RC_ALLOC(rc_expression_t, buffer, ret, scratch);
self = RC_ALLOC(rc_expression_t, parse);
next = &self->terms;
for (;;) {
*next = rc_parse_term(ret, buffer, scratch, memaddr, L, funcs_ndx);
*next = rc_parse_term(memaddr, parse);
if (*ret < 0) {
if (parse->offset < 0) {
return 0;
}

View File

@ -64,8 +64,9 @@ int rc_parse_format(const char* format_str) {
return RC_FORMAT_VALUE;
}
void rc_format_value(char* buffer, int size, unsigned value, int format) {
int rc_format_value(char* buffer, int size, unsigned value, int format) {
unsigned a, b, c;
int chars;
switch (format) {
case RC_FORMAT_FRAMES:
@ -74,13 +75,13 @@ void rc_format_value(char* buffer, int size, unsigned value, int format) {
a -= b * 100;
c = b / 60; /* minutes */
b -= c * 60;
snprintf(buffer, size, "%02u:%02u.%02u", c, b, a);
chars = snprintf(buffer, size, "%02u:%02u.%02u", c, b, a);
break;
case RC_FORMAT_SECONDS:
a = value / 60; /* minutes */
value -= a * 60;
snprintf(buffer, size, "%02u:%02u", a, value);
chars = snprintf(buffer, size, "%02u:%02u", a, value);
break;
case RC_FORMAT_CENTISECS:
@ -88,19 +89,22 @@ void rc_format_value(char* buffer, int size, unsigned value, int format) {
value -= a * 100;
b = a / 60; /* minutes */
a -= b * 60;
snprintf(buffer, size, "%02u:%02u.%02u", b, a, value);
chars = snprintf(buffer, size, "%02u:%02u.%02u", b, a, value);
break;
case RC_FORMAT_SCORE:
snprintf(buffer, size, "%06u Points", value);
chars = snprintf(buffer, size, "%06u Points", value);
break;
case RC_FORMAT_VALUE:
snprintf(buffer, size, "%01u", value);
chars = snprintf(buffer, size, "%01u", value);
break;
case RC_FORMAT_OTHER:
default:
snprintf(buffer, size, "%06u", value);
chars = snprintf(buffer, size, "%06u", value);
break;
}
return chars;
}

View File

@ -3,44 +3,83 @@
#include "rcheevos.h"
#define RC_TAG2(x,y) x ## y
#define RC_TAG(x,y) RC_TAG2(x,y)
#define RC_OFFSETOF(s, f) ((int)(long long)(&((s*)0)->f))
#define RC_ALIGNOF(t) RC_OFFSETOF(struct{char c; t d;}, d)
#define RC_ALIGNOF(t) RC_OFFSETOF(struct RC_TAG(_unnamed, __LINE__) {char c; t d;}, d)
#define RC_ALLOC(t, p, o, s) ((t*)rc_alloc(p, o, sizeof(t), RC_ALIGNOF(t), s))
#define RC_ALLOC(t, p) ((t*)rc_alloc((p)->buffer, &(p)->offset, sizeof(t), RC_ALIGNOF(t), &(p)->scratch))
typedef union {
rc_operand_t operand;
rc_condition_t condition;
rc_condset_t condset;
rc_trigger_t trigger;
rc_term_t term;
rc_expression_t expression;
rc_lboard_t lboard;
typedef struct {
rc_memref_t memref_buffer[16];
rc_memref_t *memref;
int memref_count;
int memref_size;
union
{
rc_operand_t operand;
rc_condition_t condition;
rc_condset_t condset;
rc_trigger_t trigger;
rc_term_t term;
rc_expression_t expression;
rc_lboard_t lboard;
rc_memref_value_t memref_value;
rc_richpresence_t richpresence;
rc_richpresence_display_t richpresence_display;
rc_richpresence_display_part_t richpresence_part;
rc_richpresence_lookup_t richpresence_lookup;
rc_richpresence_lookup_item_t richpresence_lookup_item;
} obj;
}
rc_scratch_t;
typedef struct {
int offset;
lua_State* L;
int funcs_ndx;
void* buffer;
rc_scratch_t scratch;
rc_memref_value_t** first_memref;
}
rc_parse_state_t;
void rc_init_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, int funcs_ndx);
void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memref_value_t** memrefs);
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);
char* rc_alloc_str(rc_parse_state_t* parse, const char* text, int length);
void rc_parse_trigger_internal(rc_trigger_t* self, int* ret, void* buffer, rc_scratch_t* scratch, const char** memaddr, lua_State* L, int funcs_ndx);
rc_memref_value_t* rc_alloc_memref_value(rc_parse_state_t* parse, unsigned address, char size, char is_bcd);
void rc_update_memref_values(rc_memref_value_t* memref, rc_peek_t peek, void* ud);
rc_condset_t* rc_parse_condset(int* ret, void* buffer, rc_scratch_t* scratch, const char** memaddr, lua_State* L, int funcs_ndx);
void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_parse_state_t* parse);
rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse);
int rc_test_condset(rc_condset_t* self, int* reset, rc_peek_t peek, void* ud, lua_State* L);
void rc_reset_condset(rc_condset_t* self);
rc_condition_t* rc_parse_condition(int* ret, void* buffer, rc_scratch_t* scratch, const char** memaddr, lua_State* L, int funcs_ndx);
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse);
int rc_test_condition(rc_condition_t* self, unsigned add_buffer, rc_peek_t peek, void* ud, lua_State* L);
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, lua_State* L, int funcs_ndx);
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, rc_parse_state_t* parse);
unsigned rc_evaluate_operand(rc_operand_t* self, rc_peek_t peek, void* ud, lua_State* L);
rc_term_t* rc_parse_term(int* ret, void* buffer, rc_scratch_t* scratch, const char** memaddr, lua_State* L, int funcs_ndx);
rc_term_t* rc_parse_term(const char** memaddr, rc_parse_state_t* parse);
unsigned rc_evaluate_term(rc_term_t* self, rc_peek_t peek, void* ud, lua_State* L);
rc_expression_t* rc_parse_expression(int* ret, void* buffer, rc_scratch_t* scratch, const char** memaddr, lua_State* L, int funcs_ndx);
rc_expression_t* rc_parse_expression(const char** memaddr, rc_parse_state_t* parse);
unsigned rc_evaluate_expression(rc_expression_t* self, rc_peek_t peek, void* ud, lua_State* L);
void rc_parse_value_internal(rc_value_t* self, int* ret, void* buffer, void* scratch, const char** memaddr, lua_State* L, int funcs_ndx);
void rc_parse_value_internal(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse);
void rc_parse_lboard_internal(rc_lboard_t* self, int* ret, void* buffer, void* scratch, const char* memaddr, lua_State* L, int funcs_ndx);
void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_state_t* parse);
void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script, rc_parse_state_t* parse);
#endif /* INTERNAL_H */

View File

@ -9,7 +9,7 @@ enum {
RC_LBOARD_COMPLETE = RC_LBOARD_START | RC_LBOARD_CANCEL | RC_LBOARD_SUBMIT | RC_LBOARD_VALUE
};
void rc_parse_lboard_internal(rc_lboard_t* self, int* ret, void* buffer, void* scratch, const char* memaddr, lua_State* L, int funcs_ndx) {
void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_state_t* parse) {
int found;
self->progress = 0;
@ -21,15 +21,16 @@ void rc_parse_lboard_internal(rc_lboard_t* self, int* ret, void* buffer, void* s
(memaddr[1] == 't' || memaddr[1] == 'T') &&
(memaddr[2] == 'a' || memaddr[2] == 'A') && memaddr[3] == ':') {
if ((found & RC_LBOARD_START) != 0) {
*ret = RC_DUPLICATED_START;
parse->offset = RC_DUPLICATED_START;
return;
}
found |= RC_LBOARD_START;
memaddr += 4;
rc_parse_trigger_internal(&self->start, ret, buffer, scratch, &memaddr, L, funcs_ndx);
rc_parse_trigger_internal(&self->start, &memaddr, parse);
self->start.memrefs = 0;
if (*ret < 0) {
if (parse->offset < 0) {
return;
}
}
@ -37,15 +38,16 @@ void rc_parse_lboard_internal(rc_lboard_t* self, int* ret, void* buffer, void* s
(memaddr[1] == 'a' || memaddr[1] == 'A') &&
(memaddr[2] == 'n' || memaddr[2] == 'N') && memaddr[3] == ':') {
if ((found & RC_LBOARD_CANCEL) != 0) {
*ret = RC_DUPLICATED_CANCEL;
parse->offset = RC_DUPLICATED_CANCEL;
return;
}
found |= RC_LBOARD_CANCEL;
memaddr += 4;
rc_parse_trigger_internal(&self->cancel, ret, buffer, scratch, &memaddr, L, funcs_ndx);
rc_parse_trigger_internal(&self->cancel, &memaddr, parse);
self->cancel.memrefs = 0;
if (*ret < 0) {
if (parse->offset < 0) {
return;
}
}
@ -53,15 +55,16 @@ void rc_parse_lboard_internal(rc_lboard_t* self, int* ret, void* buffer, void* s
(memaddr[1] == 'u' || memaddr[1] == 'U') &&
(memaddr[2] == 'b' || memaddr[2] == 'B') && memaddr[3] == ':') {
if ((found & RC_LBOARD_SUBMIT) != 0) {
*ret = RC_DUPLICATED_SUBMIT;
parse->offset = RC_DUPLICATED_SUBMIT;
return;
}
found |= RC_LBOARD_SUBMIT;
memaddr += 4;
rc_parse_trigger_internal(&self->submit, ret, buffer, scratch, &memaddr, L, funcs_ndx);
rc_parse_trigger_internal(&self->submit, &memaddr, parse);
self->submit.memrefs = 0;
if (*ret < 0) {
if (parse->offset < 0) {
return;
}
}
@ -69,15 +72,16 @@ void rc_parse_lboard_internal(rc_lboard_t* self, int* ret, void* buffer, void* s
(memaddr[1] == 'a' || memaddr[1] == 'A') &&
(memaddr[2] == 'l' || memaddr[2] == 'L') && memaddr[3] == ':') {
if ((found & RC_LBOARD_VALUE) != 0) {
*ret = RC_DUPLICATED_VALUE;
parse->offset = RC_DUPLICATED_VALUE;
return;
}
found |= RC_LBOARD_VALUE;
memaddr += 4;
rc_parse_value_internal(&self->value, ret, buffer, scratch, &memaddr, L, funcs_ndx);
rc_parse_value_internal(&self->value, &memaddr, parse);
self->value.memrefs = 0;
if (*ret < 0) {
if (parse->offset < 0) {
return;
}
}
@ -85,22 +89,23 @@ void rc_parse_lboard_internal(rc_lboard_t* self, int* ret, void* buffer, void* s
(memaddr[1] == 'r' || memaddr[1] == 'R') &&
(memaddr[2] == 'o' || memaddr[2] == 'O') && memaddr[3] == ':') {
if ((found & RC_LBOARD_PROGRESS) != 0) {
*ret = RC_DUPLICATED_PROGRESS;
parse->offset = RC_DUPLICATED_PROGRESS;
return;
}
found |= RC_LBOARD_PROGRESS;
memaddr += 4;
self->progress = RC_ALLOC(rc_value_t, buffer, ret, scratch);
rc_parse_value_internal(self->progress, ret, buffer, scratch, &memaddr, L, funcs_ndx);
self->progress = RC_ALLOC(rc_value_t, parse);
rc_parse_value_internal(self->progress, &memaddr, parse);
self->progress->memrefs = 0;
if (*ret < 0) {
if (parse->offset < 0) {
return;
}
}
else {
*ret = RC_INVALID_LBOARD_FIELD;
parse->offset = RC_INVALID_LBOARD_FIELD;
return;
}
@ -113,16 +118,16 @@ void rc_parse_lboard_internal(rc_lboard_t* self, int* ret, void* buffer, void* s
if ((found & RC_LBOARD_COMPLETE) != RC_LBOARD_COMPLETE) {
if ((found & RC_LBOARD_START) == 0) {
*ret = RC_MISSING_START;
parse->offset = RC_MISSING_START;
}
else if ((found & RC_LBOARD_CANCEL) == 0) {
*ret = RC_MISSING_CANCEL;
parse->offset = RC_MISSING_CANCEL;
}
else if ((found & RC_LBOARD_SUBMIT) == 0) {
*ret = RC_MISSING_SUBMIT;
parse->offset = RC_MISSING_SUBMIT;
}
else if ((found & RC_LBOARD_VALUE) == 0) {
*ret = RC_MISSING_VALUE;
parse->offset = RC_MISSING_VALUE;
}
return;
@ -132,31 +137,37 @@ void rc_parse_lboard_internal(rc_lboard_t* self, int* ret, void* buffer, void* s
}
int rc_lboard_size(const char* memaddr) {
int ret;
rc_lboard_t* self;
rc_scratch_t scratch;
rc_parse_state_t parse;
rc_init_parse_state(&parse, 0, 0, 0);
ret = 0;
self = RC_ALLOC(rc_lboard_t, 0, &ret, &scratch);
rc_parse_lboard_internal(self, &ret, 0, &scratch, memaddr, 0, 0);
return ret;
self = RC_ALLOC(rc_lboard_t, &parse);
rc_parse_lboard_internal(self, memaddr, &parse);
rc_destroy_parse_state(&parse);
return parse.offset;
}
rc_lboard_t* rc_parse_lboard(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx) {
int ret;
rc_lboard_t* self;
rc_scratch_t scratch;
rc_parse_state_t parse;
rc_init_parse_state(&parse, buffer, L, funcs_ndx);
ret = 0;
self = RC_ALLOC(rc_lboard_t, buffer, &ret, &scratch);
rc_parse_lboard_internal(self, &ret, buffer, 0, memaddr, L, funcs_ndx);
return ret >= 0 ? self : 0;
self = RC_ALLOC(rc_lboard_t, &parse);
rc_init_parse_state_memrefs(&parse, &self->memrefs);
rc_parse_lboard_internal(self, memaddr, &parse);
rc_destroy_parse_state(&parse);
return parse.offset >= 0 ? self : 0;
}
int rc_evaluate_lboard(rc_lboard_t* self, unsigned* value, rc_peek_t peek, void* peek_ud, lua_State* L) {
int start_ok, cancel_ok, submit_ok;
int action = -1;
rc_update_memref_values(self->memrefs, peek, peek_ud);
/* ASSERT: these are always tested once every frame, to ensure delta variables work properly */
start_ok = rc_test_trigger(&self->start, peek, peek_ud, L);
cancel_ok = rc_test_trigger(&self->cancel, peek, peek_ud, L);

204
deps/rcheevos/src/rcheevos/memref.c vendored Normal file
View File

@ -0,0 +1,204 @@
#include "internal.h"
#include <stdlib.h> /* malloc/realloc */
#include <string.h> /* memcpy */
rc_memref_value_t* rc_alloc_memref_value(rc_parse_state_t* parse, unsigned address, char size, char is_bcd) {
rc_memref_value_t** next_memref_value;
rc_memref_value_t* memref_value;
rc_memref_t* memref;
int i;
if (!parse->first_memref) {
/* sizing mode - have to track unique address/size/bcd combinations */
for (i = 0; i < parse->scratch.memref_count; ++i) {
memref = &parse->scratch.memref[i];
if (memref->address == address && memref->size == size && memref->is_bcd == is_bcd) {
return &parse->scratch.obj.memref_value;
}
}
/* resize unique tracking buffer if necessary */
if (parse->scratch.memref_count == parse->scratch.memref_size) {
if (parse->scratch.memref == parse->scratch.memref_buffer) {
parse->scratch.memref_size += 16;
memref = malloc(parse->scratch.memref_size * sizeof(parse->scratch.memref_buffer[0]));
if (memref) {
parse->scratch.memref = memref;
memcpy(memref, parse->scratch.memref_buffer, parse->scratch.memref_count * sizeof(parse->scratch.memref_buffer[0]));
}
else {
parse->offset = RC_OUT_OF_MEMORY;
return 0;
}
}
else {
parse->scratch.memref_size += 32;
memref = realloc(parse->scratch.memref, parse->scratch.memref_size * sizeof(parse->scratch.memref_buffer[0]));
if (memref) {
parse->scratch.memref = memref;
}
else {
parse->offset = RC_OUT_OF_MEMORY;
return 0;
}
}
}
/* add new unique tracking entry */
if (parse->scratch.memref) {
memref = &parse->scratch.memref[parse->scratch.memref_count++];
memref->address = address;
memref->size = size;
memref->is_bcd = is_bcd;
}
/* allocate memory but don't actually populate, as it might overwrite the self object referencing the rc_memref_value_t */
return RC_ALLOC(rc_memref_value_t, parse);
}
/* construction mode - find or create the appropriate rc_memref_value_t */
next_memref_value = parse->first_memref;
while (*next_memref_value) {
memref_value = *next_memref_value;
if (memref_value->memref.address == address && memref_value->memref.size == size && memref_value->memref.is_bcd == is_bcd) {
return memref_value;
}
next_memref_value = &memref_value->next;
}
memref_value = RC_ALLOC(rc_memref_value_t, parse);
memref_value->memref.address = address;
memref_value->memref.size = size;
memref_value->memref.is_bcd = is_bcd;
memref_value->value = 0;
memref_value->previous = 0;
memref_value->prior = 0;
memref_value->next = 0;
*next_memref_value = memref_value;
return memref_value;
}
static unsigned rc_memref_get_value(rc_memref_t* self, rc_peek_t peek, void* ud) {
unsigned value;
switch (self->size)
{
case RC_MEMSIZE_BIT_0:
value = (peek(self->address, 1, ud) >> 0) & 1;
break;
case RC_MEMSIZE_BIT_1:
value = (peek(self->address, 1, ud) >> 1) & 1;
break;
case RC_MEMSIZE_BIT_2:
value = (peek(self->address, 1, ud) >> 2) & 1;
break;
case RC_MEMSIZE_BIT_3:
value = (peek(self->address, 1, ud) >> 3) & 1;
break;
case RC_MEMSIZE_BIT_4:
value = (peek(self->address, 1, ud) >> 4) & 1;
break;
case RC_MEMSIZE_BIT_5:
value = (peek(self->address, 1, ud) >> 5) & 1;
break;
case RC_MEMSIZE_BIT_6:
value = (peek(self->address, 1, ud) >> 6) & 1;
break;
case RC_MEMSIZE_BIT_7:
value = (peek(self->address, 1, ud) >> 7) & 1;
break;
case RC_MEMSIZE_LOW:
value = peek(self->address, 1, ud) & 0x0f;
break;
case RC_MEMSIZE_HIGH:
value = (peek(self->address, 1, ud) >> 4) & 0x0f;
break;
case RC_MEMSIZE_8_BITS:
value = peek(self->address, 1, ud);
if (self->is_bcd) {
value = ((value >> 4) & 0x0f) * 10 + (value & 0x0f);
}
break;
case RC_MEMSIZE_16_BITS:
value = peek(self->address, 2, ud);
if (self->is_bcd) {
value = ((value >> 12) & 0x0f) * 1000
+ ((value >> 8) & 0x0f) * 100
+ ((value >> 4) & 0x0f) * 10
+ ((value >> 0) & 0x0f) * 1;
}
break;
case RC_MEMSIZE_24_BITS:
value = peek(self->address, 4, ud);
if (self->is_bcd) {
value = ((value >> 20) & 0x0f) * 100000
+ ((value >> 16) & 0x0f) * 10000
+ ((value >> 12) & 0x0f) * 1000
+ ((value >> 8) & 0x0f) * 100
+ ((value >> 4) & 0x0f) * 10
+ ((value >> 0) & 0x0f) * 1;
}
break;
case RC_MEMSIZE_32_BITS:
value = peek(self->address, 4, ud);
if (self->is_bcd) {
value = ((value >> 28) & 0x0f) * 10000000
+ ((value >> 24) & 0x0f) * 1000000
+ ((value >> 20) & 0x0f) * 100000
+ ((value >> 16) & 0x0f) * 10000
+ ((value >> 12) & 0x0f) * 1000
+ ((value >> 8) & 0x0f) * 100
+ ((value >> 4) & 0x0f) * 10
+ ((value >> 0) & 0x0f) * 1;
}
break;
default:
value = 0;
break;
}
return value;
}
void rc_update_memref_values(rc_memref_value_t* memref, rc_peek_t peek, void* ud) {
while (memref) {
memref->previous = memref->value;
memref->value = rc_memref_get_value(&memref->memref, peek, ud);
if (memref->value != memref->previous)
memref->prior = memref->previous;
memref = memref->next;
}
}
void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memref_value_t** memrefs)
{
parse->first_memref = memrefs;
*memrefs = 0;
}

View File

@ -2,6 +2,7 @@
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#ifndef RC_DISABLE_LUA
@ -18,7 +19,7 @@ extern "C" {
#endif /* RC_DISABLE_LUA */
static int rc_parse_operand_lua(rc_operand_t* self, const char** memaddr, lua_State* L, int funcs_ndx) {
static int rc_parse_operand_lua(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
const char* aux = *memaddr;
const char* id;
@ -38,20 +39,20 @@ static int rc_parse_operand_lua(rc_operand_t* self, const char** memaddr, lua_St
#ifndef RC_DISABLE_LUA
if (L != 0) {
if (!lua_istable(L, funcs_ndx)) {
if (parse->L != 0) {
if (!lua_istable(parse->L, parse->funcs_ndx)) {
return RC_INVALID_LUA_OPERAND;
}
lua_pushlstring(L, id, aux - id);
lua_gettable(L, funcs_ndx);
lua_pushlstring(parse->L, id, aux - id);
lua_gettable(parse->L, parse->funcs_ndx);
if (!lua_isfunction(L, -1)) {
lua_pop(L, 1);
if (!lua_isfunction(parse->L, -1)) {
lua_pop(parse->L, 1);
return RC_INVALID_LUA_OPERAND;
}
self->function_ref = luaL_ref(L, LUA_REGISTRYINDEX);
self->function_ref = luaL_ref(parse->L, LUA_REGISTRYINDEX);
}
#endif /* RC_DISABLE_LUA */
@ -61,10 +62,12 @@ static int rc_parse_operand_lua(rc_operand_t* self, const char** memaddr, lua_St
return RC_OK;
}
static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr) {
static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
const char* aux = *memaddr;
char* end;
unsigned long value;
unsigned long address;
char is_bcd = 0;
char size;
switch (*aux++) {
case 'd': case 'D':
@ -73,7 +76,11 @@ static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr) {
case 'b': case 'B':
self->type = RC_OPERAND_ADDRESS;
self->is_bcd = 1;
is_bcd = 1;
break;
case 'p': case 'P':
self->type = RC_OPERAND_PRIOR;
break;
default:
@ -93,44 +100,46 @@ static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr) {
aux++;
switch (*aux++) {
case 'm': case 'M': self->size = RC_OPERAND_BIT_0; break;
case 'n': case 'N': self->size = RC_OPERAND_BIT_1; break;
case 'o': case 'O': self->size = RC_OPERAND_BIT_2; break;
case 'p': case 'P': self->size = RC_OPERAND_BIT_3; break;
case 'q': case 'Q': self->size = RC_OPERAND_BIT_4; break;
case 'r': case 'R': self->size = RC_OPERAND_BIT_5; break;
case 's': case 'S': self->size = RC_OPERAND_BIT_6; break;
case 't': case 'T': self->size = RC_OPERAND_BIT_7; break;
case 'l': case 'L': self->size = RC_OPERAND_LOW; break;
case 'u': case 'U': self->size = RC_OPERAND_HIGH; break;
case 'h': case 'H': self->size = RC_OPERAND_8_BITS; break;
case 'w': case 'W': self->size = RC_OPERAND_24_BITS; break;
case 'x': case 'X': self->size = RC_OPERAND_32_BITS; break;
case 'm': case 'M': size = RC_MEMSIZE_BIT_0; break;
case 'n': case 'N': size = RC_MEMSIZE_BIT_1; break;
case 'o': case 'O': size = RC_MEMSIZE_BIT_2; break;
case 'p': case 'P': size = RC_MEMSIZE_BIT_3; break;
case 'q': case 'Q': size = RC_MEMSIZE_BIT_4; break;
case 'r': case 'R': size = RC_MEMSIZE_BIT_5; break;
case 's': case 'S': size = RC_MEMSIZE_BIT_6; break;
case 't': case 'T': size = RC_MEMSIZE_BIT_7; break;
case 'l': case 'L': size = RC_MEMSIZE_LOW; break;
case 'u': case 'U': size = RC_MEMSIZE_HIGH; break;
case 'h': case 'H': size = RC_MEMSIZE_8_BITS; break;
case 'w': case 'W': size = RC_MEMSIZE_24_BITS; break;
case 'x': case 'X': size = RC_MEMSIZE_32_BITS; break;
default: /* fall through */
aux--;
case ' ':
self->size = RC_OPERAND_16_BITS;
size = RC_MEMSIZE_16_BITS;
break;
}
value = (unsigned)strtoul(aux, &end, 16);
address = strtoul(aux, &end, 16);
if (end == aux) {
return RC_INVALID_MEMORY_OPERAND;
}
if (value > 0xffffffffU) {
value = 0xffffffffU;
if (address > 0xffffffffU) {
address = 0xffffffffU;
}
self->value = (unsigned)value;
self->memref = rc_alloc_memref_value(parse, address, size, is_bcd);
if (parse->offset < 0)
return parse->offset;
*memaddr = end;
return RC_OK;
}
static int rc_parse_operand_trigger(rc_operand_t* self, const char** memaddr, lua_State* L, int funcs_ndx) {
static int rc_parse_operand_trigger(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
const char* aux = *memaddr;
char* end;
int ret;
@ -158,7 +167,7 @@ static int rc_parse_operand_trigger(rc_operand_t* self, const char** memaddr, lu
if (aux[1] == 'x' || aux[1] == 'X') {
/* fall through */
default:
ret = rc_parse_operand_memory(self, &aux);
ret = rc_parse_operand_memory(self, &aux, parse);
if (ret < 0) {
return ret;
@ -188,7 +197,7 @@ static int rc_parse_operand_trigger(rc_operand_t* self, const char** memaddr, lu
break;
case '@':
ret = rc_parse_operand_lua(self, &aux, L, funcs_ndx);
ret = rc_parse_operand_lua(self, &aux, parse);
if (ret < 0) {
return ret;
@ -201,7 +210,7 @@ static int rc_parse_operand_trigger(rc_operand_t* self, const char** memaddr, lu
return RC_OK;
}
static int rc_parse_operand_term(rc_operand_t* self, const char** memaddr, lua_State* L, int funcs_ndx) {
static int rc_parse_operand_term(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
const char* aux = *memaddr;
char* end;
int ret;
@ -209,7 +218,7 @@ static int rc_parse_operand_term(rc_operand_t* self, const char** memaddr, lua_S
switch (*aux) {
case 'h': case 'H':
value = (unsigned)strtoul(++aux, &end, 16);
value = strtoul(++aux, &end, 16);
if (end == aux) {
return RC_INVALID_CONST_OPERAND;
@ -226,7 +235,7 @@ static int rc_parse_operand_term(rc_operand_t* self, const char** memaddr, lua_S
break;
case 'v': case 'V':
value = (unsigned)strtoul(++aux, &end, 10);
value = strtoul(++aux, &end, 10);
if (end == aux) {
return RC_INVALID_CONST_OPERAND;
@ -246,7 +255,7 @@ static int rc_parse_operand_term(rc_operand_t* self, const char** memaddr, lua_S
if (aux[1] == 'x' || aux[1] == 'X') {
/* fall through */
default:
ret = rc_parse_operand_memory(self, &aux);
ret = rc_parse_operand_memory(self, &aux, parse);
if (ret < 0) {
return ret;
@ -256,21 +265,28 @@ static int rc_parse_operand_term(rc_operand_t* self, const char** memaddr, lua_S
}
/* fall through */
case '.':
case '+': case '-':
case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
self->type = RC_OPERAND_FP;
self->fp_value = strtod(aux, &end);
if (end == aux) {
return RC_INVALID_FP_OPERAND;
}
if (floor(self->fp_value) == self->fp_value) {
self->type = RC_OPERAND_CONST;
self->value = (unsigned)floor(self->fp_value);
}
else {
self->type = RC_OPERAND_FP;
}
aux = end;
break;
case '@':
ret = rc_parse_operand_lua(self, &aux, L, funcs_ndx);
ret = rc_parse_operand_lua(self, &aux, parse);
if (ret < 0) {
return ret;
@ -283,16 +299,12 @@ static int rc_parse_operand_term(rc_operand_t* self, const char** memaddr, lua_S
return RC_OK;
}
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, lua_State* L, int funcs_ndx) {
self->size = RC_OPERAND_8_BITS;
self->is_bcd = 0;
self->previous = 0;
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, rc_parse_state_t* parse) {
if (is_trigger) {
return rc_parse_operand_trigger(self, memaddr, L, funcs_ndx);
return rc_parse_operand_trigger(self, memaddr, parse);
}
else {
return rc_parse_operand_term(self, memaddr, L, funcs_ndx);
return rc_parse_operand_term(self, memaddr, parse);
}
}
@ -362,106 +374,15 @@ unsigned rc_evaluate_operand(rc_operand_t* self, rc_peek_t peek, void* ud, lua_S
break;
case RC_OPERAND_ADDRESS:
value = self->memref->value;
break;
case RC_OPERAND_DELTA:
switch (self->size) {
case RC_OPERAND_BIT_0:
value = (peek(self->value, 1, ud) >> 0) & 1;
break;
case RC_OPERAND_BIT_1:
value = (peek(self->value, 1, ud) >> 1) & 1;
break;
case RC_OPERAND_BIT_2:
value = (peek(self->value, 1, ud) >> 2) & 1;
break;
case RC_OPERAND_BIT_3:
value = (peek(self->value, 1, ud) >> 3) & 1;
break;
case RC_OPERAND_BIT_4:
value = (peek(self->value, 1, ud) >> 4) & 1;
break;
case RC_OPERAND_BIT_5:
value = (peek(self->value, 1, ud) >> 5 ) & 1;
break;
case RC_OPERAND_BIT_6:
value = (peek(self->value, 1, ud) >> 6) & 1;
break;
case RC_OPERAND_BIT_7:
value = (peek(self->value, 1, ud) >> 7) & 1;
break;
case RC_OPERAND_LOW:
value = peek(self->value, 1, ud) & 0x0f;
break;
case RC_OPERAND_HIGH:
value = (peek(self->value, 1, ud) >> 4) & 0x0f;
break;
case RC_OPERAND_8_BITS:
value = peek(self->value, 1, ud);
if (self->is_bcd) {
value = ((value >> 4) & 0x0f) * 10 + (value & 0x0f);
}
break;
case RC_OPERAND_16_BITS:
value = peek(self->value, 2, ud);
if (self->is_bcd) {
value = ((value >> 12) & 0x0f) * 1000
+ ((value >> 8) & 0x0f) * 100
+ ((value >> 4) & 0x0f) * 10
+ ((value >> 0) & 0x0f) * 1;
}
break;
case RC_OPERAND_24_BITS:
value = peek(self->value, 4, ud);
if (self->is_bcd) {
value = ((value >> 20) & 0x0f) * 100000
+ ((value >> 16) & 0x0f) * 10000
+ ((value >> 12) & 0x0f) * 1000
+ ((value >> 8) & 0x0f) * 100
+ ((value >> 4) & 0x0f) * 10
+ ((value >> 0) & 0x0f) * 1;
}
break;
case RC_OPERAND_32_BITS:
value = peek(self->value, 4, ud);
if (self->is_bcd) {
value = ((value >> 28) & 0x0f) * 10000000
+ ((value >> 24) & 0x0f) * 1000000
+ ((value >> 20) & 0x0f) * 100000
+ ((value >> 16) & 0x0f) * 10000
+ ((value >> 12) & 0x0f) * 1000
+ ((value >> 8) & 0x0f) * 100
+ ((value >> 4) & 0x0f) * 10
+ ((value >> 0) & 0x0f) * 1;
}
break;
}
if (self->type == RC_OPERAND_DELTA) {
unsigned previous = self->previous;
self->previous = value;
value = previous;
}
value = self->memref->previous;
break;
case RC_OPERAND_PRIOR:
value = self->memref->prior;
break;
}

View File

@ -0,0 +1,430 @@
#include "internal.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* special formats only used by rc_richpresence_display_part_t.display_type. must not overlap other RC_FORMAT values */
enum {
RC_FORMAT_STRING = 101,
RC_FORMAT_LOOKUP = 102
};
static const char* rc_parse_line(const char* line, const char** end) {
const char* nextline;
const char* endline;
/* get a single line */
nextline = line;
while (*nextline && *nextline != '\n')
++nextline;
/* find a trailing comment marker (//) */
endline = line;
while (endline < nextline && (endline[0] != '/' || endline[1] != '/' || (endline > line && endline[-1] == '\\')))
++endline;
/* remove trailing whitespace */
if (endline == nextline) {
if (endline > line && endline[-1] == '\r')
--endline;
} else {
while (endline > line && isspace(endline[-1]))
--endline;
}
/* end is pointing at the first character to ignore - makes subtraction for length easier */
*end = endline;
if (*nextline == '\n')
++nextline;
return nextline;
}
static rc_richpresence_display_t* rc_parse_richpresence_display_internal(const char* line, const char* endline, rc_parse_state_t* parse, rc_richpresence_t* richpresence) {
rc_richpresence_display_t* self;
rc_richpresence_display_part_t* part;
rc_richpresence_display_part_t** next;
rc_richpresence_lookup_t* lookup;
const char* ptr;
const char* in;
char* out;
if (endline - line < 1)
return 0;
{
self = RC_ALLOC(rc_richpresence_display_t, parse);
memset(self, 0, sizeof(rc_richpresence_display_t));
next = &self->display;
}
/* break the string up on macros: text @macro() moretext */
do {
ptr = line;
while (ptr < endline) {
if (*ptr == '@' && (ptr == line || ptr[-1] != '\\')) /* ignore escaped @s */
break;
++ptr;
}
if (ptr > line) {
part = RC_ALLOC(rc_richpresence_display_part_t, parse);
memset(part, 0, sizeof(rc_richpresence_display_part_t));
*next = part;
next = &part->next;
/* handle string part */
part->display_type = RC_FORMAT_STRING;
part->text = rc_alloc_str(parse, line, ptr - line);
if (part->text) {
/* remove backslashes used for escaping */
in = part->text;
while (*in && *in != '\\')
++in;
if (*in == '\\') {
out = (char*)in++;
while (*in) {
*out++ = *in++;
if (*in == '\\')
++in;
}
*out = '\0';
}
}
}
if (*ptr == '@') {
/* handle macro part */
line = ++ptr;
while (ptr < endline && *ptr != '(')
++ptr;
if (ptr > line) {
if (!parse->buffer) {
/* just calculating size, can't confirm lookup exists */
part = RC_ALLOC(rc_richpresence_display_part_t, parse);
line = ++ptr;
while (ptr < endline && *ptr != ')')
++ptr;
if (*ptr == ')') {
rc_parse_value_internal(&part->value, &line, parse);
if (parse->offset < 0)
return 0;
++ptr;
}
} else {
/* find the lookup and hook it up */
lookup = richpresence->first_lookup;
while (lookup) {
if (strncmp(lookup->name, line, ptr - line) == 0 && lookup->name[ptr - line] == '\0') {
part = RC_ALLOC(rc_richpresence_display_part_t, parse);
*next = part;
next = &part->next;
part->text = lookup->name;
part->first_lookup_item = lookup->first_item;
part->display_type = lookup->format;
line = ++ptr;
while (ptr < endline && *ptr != ')')
++ptr;
if (*ptr == ')') {
rc_parse_value_internal(&part->value, &line, parse);
part->value.memrefs = 0;
if (parse->offset < 0)
return 0;
++ptr;
}
break;
}
lookup = lookup->next;
}
if (!lookup) {
part = RC_ALLOC(rc_richpresence_display_part_t, parse);
memset(part, 0, sizeof(rc_richpresence_display_part_t));
*next = part;
next = &part->next;
ptr = line;
part->display_type = RC_FORMAT_STRING;
part->text = rc_alloc_str(parse, "[Unknown macro]", 15);
}
}
}
}
line = ptr;
} while (line < endline);
*next = 0;
return self;
}
static const char* rc_parse_richpresence_lookup(rc_richpresence_lookup_t* lookup, const char* nextline, rc_parse_state_t* parse)
{
rc_richpresence_lookup_item_t** next;
rc_richpresence_lookup_item_t* item;
char number[64];
const char* line;
const char* endline;
const char* defaultlabel = 0;
unsigned key;
int chars;
next = &lookup->first_item;
do
{
line = nextline;
nextline = rc_parse_line(line, &endline);
if (endline - line < 2)
break;
chars = 0;
while (chars < (sizeof(number) - 1) && line + chars < endline && line[chars] != '=') {
number[chars] = line[chars];
++chars;
}
number[chars] = '\0';
if (line[chars] == '=') {
line += chars + 1;
if (chars == 1 && number[0] == '*') {
defaultlabel = rc_alloc_str(parse, line, endline - line);
continue;
}
if (number[0] == '0' && number[1] == 'x')
key = strtoul(&number[2], 0, 16);
else
key = strtoul(&number[0], 0, 10);
item = RC_ALLOC(rc_richpresence_lookup_item_t, parse);
item->value = key;
item->label = rc_alloc_str(parse, line, endline - line);
*next = item;
next = &item->next_item;
}
} while (1);
if (!defaultlabel)
defaultlabel = rc_alloc_str(parse, "", 0);
item = RC_ALLOC(rc_richpresence_lookup_item_t, parse);
item->value = 0;
item->label = defaultlabel;
item->next_item = 0;
*next = item;
return nextline;
}
void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script, rc_parse_state_t* parse) {
rc_richpresence_display_t** nextdisplay;
rc_richpresence_lookup_t** nextlookup;
rc_richpresence_lookup_t* lookup;
rc_trigger_t* trigger;
char format[64];
const char* display = 0;
const char* line;
const char* nextline;
const char* endline;
const char* ptr;
int hasdisplay = 0;
int chars;
nextlookup = &self->first_lookup;
/* first pass: process macro initializers */
line = script;
while (*line)
{
nextline = rc_parse_line(line, &endline);
if (strncmp(line, "Lookup:", 7) == 0) {
line += 7;
lookup = RC_ALLOC(rc_richpresence_lookup_t, parse);
lookup->name = rc_alloc_str(parse, line, endline - line);
lookup->format = RC_FORMAT_LOOKUP;
*nextlookup = lookup;
nextlookup = &lookup->next;
nextline = rc_parse_richpresence_lookup(lookup, nextline, parse);
} else if (strncmp(line, "Format:", 7) == 0) {
line += 7;
lookup = RC_ALLOC(rc_richpresence_lookup_t, parse);
lookup->name = rc_alloc_str(parse, line, endline - line);
lookup->first_item = 0;
*nextlookup = lookup;
nextlookup = &lookup->next;
line = nextline;
nextline = rc_parse_line(line, &endline);
if (parse->buffer && strncmp(line, "FormatType=", 11) == 0) {
line += 11;
chars = endline - line;
if (chars > 63)
chars = 63;
memcpy(format, line, chars);
format[chars] = '\0';
lookup->format = rc_parse_format(format);
} else {
lookup->format = RC_FORMAT_VALUE;
}
} else if (strncmp(line, "Display:", 8) == 0) {
display = nextline;
do {
line = nextline;
nextline = rc_parse_line(line, &endline);
} while (*line == '?');
}
line = nextline;
}
*nextlookup = 0;
nextdisplay = &self->first_display;
/* second pass, process display string*/
if (display) {
line = display;
nextline = rc_parse_line(line, &endline);
while (*line == '?') {
/* conditional display: ?trigger?string */
ptr = ++line;
while (ptr < endline && *ptr != '?')
++ptr;
if (ptr < endline) {
*nextdisplay = rc_parse_richpresence_display_internal(ptr + 1, endline, parse, self);
trigger = &((*nextdisplay)->trigger);
rc_parse_trigger_internal(trigger, &line, parse);
trigger->memrefs = 0;
if (parse->offset < 0)
return;
if (parse->buffer)
nextdisplay = &((*nextdisplay)->next);
}
line = nextline;
nextline = rc_parse_line(line, &endline);
}
/* non-conditional display: string */
*nextdisplay = rc_parse_richpresence_display_internal(line, endline, parse, self);
if (*nextdisplay) {
hasdisplay = 1;
nextdisplay = &((*nextdisplay)->next);
}
}
/* finalize */
*nextdisplay = 0;
if (!hasdisplay && parse->offset > 0) {
parse->offset = RC_MISSING_DISPLAY_STRING;
}
}
int rc_richpresence_size(const char* script) {
rc_richpresence_t* self;
rc_parse_state_t parse;
rc_init_parse_state(&parse, 0, 0, 0);
self = RC_ALLOC(rc_richpresence_t, &parse);
rc_parse_richpresence_internal(self, script, &parse);
rc_destroy_parse_state(&parse);
return parse.offset;
}
rc_richpresence_t* rc_parse_richpresence(void* buffer, const char* script, lua_State* L, int funcs_ndx) {
rc_richpresence_t* self;
rc_parse_state_t parse;
rc_init_parse_state(&parse, buffer, L, funcs_ndx);
self = RC_ALLOC(rc_richpresence_t, &parse);
rc_init_parse_state_memrefs(&parse, &self->memrefs);
rc_parse_richpresence_internal(self, script, &parse);
rc_destroy_parse_state(&parse);
return parse.offset >= 0 ? self : 0;
}
int rc_evaluate_richpresence(rc_richpresence_t* richpresence, char* buffer, unsigned buffersize, rc_peek_t peek, void* peek_ud, lua_State* L) {
rc_richpresence_display_t* display;
rc_richpresence_display_part_t* part;
rc_richpresence_lookup_item_t* item;
char* ptr;
int chars;
unsigned value;
rc_update_memref_values(richpresence->memrefs, peek, peek_ud);
ptr = buffer;
display = richpresence->first_display;
while (display) {
if (!display->next || rc_test_trigger(&display->trigger, peek, peek_ud, L)) {
part = display->display;
while (part) {
switch (part->display_type) {
case RC_FORMAT_STRING:
chars = snprintf(ptr, buffersize, "%s", part->text);
break;
case RC_FORMAT_LOOKUP:
value = rc_evaluate_value(&part->value, peek, peek_ud, L);
item = part->first_lookup_item;
if (!item) {
chars = 0;
} else {
while (item->next_item && item->value != value)
item = item->next_item;
chars = snprintf(ptr, buffersize, "%s", item->label);
}
break;
default:
value = rc_evaluate_value(&part->value, peek, peek_ud, L);
chars = rc_format_value(ptr, buffersize, value, part->display_type);
break;
}
if (chars > 0) {
ptr += chars;
buffersize -= chars;
}
part = part->next;
}
return (ptr - buffer);
}
display = display->next;
}
buffer[0] = '\0';
return 0;
}

View File

@ -1,18 +1,19 @@
#include "internal.h"
rc_term_t* rc_parse_term(int* ret, void* buffer, rc_scratch_t* scratch, const char** memaddr, lua_State* L, int funcs_ndx) {
rc_term_t* rc_parse_term(const char** memaddr, rc_parse_state_t* parse) {
rc_term_t* self;
const char* aux;
char size;
int ret2;
aux = *memaddr;
self = RC_ALLOC(rc_term_t, buffer, ret, scratch);
self = RC_ALLOC(rc_term_t, parse);
self->invert = 0;
ret2 = rc_parse_operand(&self->operand1, &aux, 0, L, funcs_ndx);
ret2 = rc_parse_operand(&self->operand1, &aux, 0, parse);
if (ret2 < 0) {
*ret = ret2;
parse->offset = ret2;
return 0;
}
@ -24,53 +25,63 @@ rc_term_t* rc_parse_term(int* ret, void* buffer, rc_scratch_t* scratch, const ch
self->invert = 1;
}
ret2 = rc_parse_operand(&self->operand2, &aux, 0, L, funcs_ndx);
ret2 = rc_parse_operand(&self->operand2, &aux, 0, parse);
if (ret2 < 0) {
*ret = ret2;
parse->offset = ret2;
return 0;
}
if (self->invert) {
switch (self->operand2.size) {
case RC_OPERAND_BIT_0:
case RC_OPERAND_BIT_1:
case RC_OPERAND_BIT_2:
case RC_OPERAND_BIT_3:
case RC_OPERAND_BIT_4:
case RC_OPERAND_BIT_5:
case RC_OPERAND_BIT_6:
case RC_OPERAND_BIT_7:
switch (self->operand2.type) {
case RC_OPERAND_ADDRESS:
case RC_OPERAND_DELTA:
case RC_OPERAND_PRIOR:
size = self->operand2.memref->memref.size;
break;
default:
size = RC_MEMSIZE_32_BITS;
break;
}
switch (size) {
case RC_MEMSIZE_BIT_0:
case RC_MEMSIZE_BIT_1:
case RC_MEMSIZE_BIT_2:
case RC_MEMSIZE_BIT_3:
case RC_MEMSIZE_BIT_4:
case RC_MEMSIZE_BIT_5:
case RC_MEMSIZE_BIT_6:
case RC_MEMSIZE_BIT_7:
/* invert is already 1 */
break;
case RC_OPERAND_LOW:
case RC_OPERAND_HIGH:
case RC_MEMSIZE_LOW:
case RC_MEMSIZE_HIGH:
self->invert = 0xf;
break;
case RC_OPERAND_8_BITS:
case RC_MEMSIZE_8_BITS:
self->invert = 0xffU;
break;
case RC_OPERAND_16_BITS:
case RC_MEMSIZE_16_BITS:
self->invert = 0xffffU;
break;
case RC_OPERAND_24_BITS:
case RC_MEMSIZE_24_BITS:
self->invert = 0xffffffU;
break;
case RC_OPERAND_32_BITS:
case RC_MEMSIZE_32_BITS:
self->invert = 0xffffffffU;
break;
}
}
}
else {
self->operand2.type = RC_OPERAND_FP;
self->operand2.size = RC_OPERAND_8_BITS;
self->operand2.fp_value = 1.0;
self->operand2.type = RC_OPERAND_CONST;
self->operand2.value = 1;
}
*memaddr = aux;
@ -84,5 +95,5 @@ unsigned rc_evaluate_term(rc_term_t* self, rc_peek_t peek, void* ud, lua_State*
return value * (rc_evaluate_operand(&self->operand2, peek, ud, L) ^ self->invert);
}
return (unsigned)(value * self->operand2.fp_value);
return (unsigned)((double)value * self->operand2.fp_value);
}

View File

@ -2,7 +2,7 @@
#include <stddef.h>
void rc_parse_trigger_internal(rc_trigger_t* self, int* ret, void* buffer, rc_scratch_t* scratch, const char** memaddr, lua_State* L, int funcs_ndx) {
void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_parse_state_t* parse) {
rc_condset_t** next;
const char* aux;
@ -13,18 +13,20 @@ void rc_parse_trigger_internal(rc_trigger_t* self, int* ret, void* buffer, rc_sc
self->requirement = 0;
}
else {
self->requirement = rc_parse_condset(ret, buffer, scratch, &aux, L, funcs_ndx);
self->requirement = rc_parse_condset(&aux, parse);
if (*ret < 0) {
if (parse->offset < 0) {
return;
}
self->requirement->next = 0;
}
while (*aux == 's' || *aux == 'S') {
aux++;
*next = rc_parse_condset(ret, buffer, scratch, &aux, L, funcs_ndx);
*next = rc_parse_condset(&aux, parse);
if (*ret < 0) {
if (parse->offset < 0) {
return;
}
@ -36,31 +38,37 @@ void rc_parse_trigger_internal(rc_trigger_t* self, int* ret, void* buffer, rc_sc
}
int rc_trigger_size(const char* memaddr) {
int ret;
rc_trigger_t* self;
rc_scratch_t scratch;
rc_parse_state_t parse;
rc_init_parse_state(&parse, 0, 0, 0);
ret = 0;
self = RC_ALLOC(rc_trigger_t, 0, &ret, &scratch);
rc_parse_trigger_internal(self, &ret, 0, &scratch, &memaddr, 0, 0);
return ret;
self = RC_ALLOC(rc_trigger_t, &parse);
rc_parse_trigger_internal(self, &memaddr, &parse);
rc_destroy_parse_state(&parse);
return parse.offset;
}
rc_trigger_t* rc_parse_trigger(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx) {
int ret;
rc_trigger_t* self;
rc_scratch_t scratch;
rc_parse_state_t parse;
rc_init_parse_state(&parse, buffer, L, funcs_ndx);
ret = 0;
self = RC_ALLOC(rc_trigger_t, buffer, &ret, &scratch);
rc_parse_trigger_internal(self, &ret, buffer, 0, &memaddr, L, funcs_ndx);
return ret >= 0 ? self : 0;
self = RC_ALLOC(rc_trigger_t, &parse);
rc_init_parse_state_memrefs(&parse, &self->memrefs);
rc_parse_trigger_internal(self, &memaddr, &parse);
rc_destroy_parse_state(&parse);
return parse.offset >= 0 ? self : 0;
}
int rc_test_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State* L) {
int ret, reset;
rc_condset_t* condset;
rc_update_memref_values(self->memrefs, peek, ud);
reset = 0;
ret = self->requirement != 0 ? rc_test_condset(self->requirement, &reset, peek, ud, L) : 1;
condset = self->alternative;

View File

@ -1,14 +1,14 @@
#include "internal.h"
void rc_parse_value_internal(rc_value_t* self, int* ret, void* buffer, void* scratch, const char** memaddr, lua_State* L, int funcs_ndx) {
void rc_parse_value_internal(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse) {
rc_expression_t** next;
next = &self->expressions;
for (;;) {
*next = rc_parse_expression(ret, buffer, scratch, memaddr, L, funcs_ndx);
*next = rc_parse_expression(memaddr, parse);
if (*ret < 0) {
if (parse->offset < 0) {
return;
}
@ -25,31 +25,37 @@ void rc_parse_value_internal(rc_value_t* self, int* ret, void* buffer, void* scr
}
int rc_value_size(const char* memaddr) {
int ret;
rc_value_t* self;
rc_scratch_t scratch;
rc_parse_state_t parse;
rc_init_parse_state(&parse, 0, 0, 0);
ret = 0;
self = RC_ALLOC(rc_value_t, 0, &ret, &scratch);
rc_parse_value_internal(self, &ret, 0, &scratch, &memaddr, 0, 0);
return ret;
self = RC_ALLOC(rc_value_t, &parse);
rc_parse_value_internal(self, &memaddr, &parse);
rc_destroy_parse_state(&parse);
return parse.offset;
}
rc_value_t* rc_parse_value(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx) {
int ret;
rc_value_t* self;
rc_scratch_t scratch;
rc_parse_state_t parse;
rc_init_parse_state(&parse, buffer, L, funcs_ndx);
ret = 0;
self = RC_ALLOC(rc_value_t, buffer, &ret, &scratch);
rc_parse_value_internal(self, &ret, buffer, 0, &memaddr, L, funcs_ndx);
return ret >= 0 ? self : 0;
self = RC_ALLOC(rc_value_t, &parse);
rc_init_parse_state_memrefs(&parse, &self->memrefs);
rc_parse_value_internal(self, &memaddr, &parse);
rc_destroy_parse_state(&parse);
return parse.offset >= 0 ? self : 0;
}
unsigned rc_evaluate_value(rc_value_t* self, rc_peek_t peek, void* ud, lua_State* L) {
rc_expression_t* exp;
unsigned value, max;
rc_update_memref_values(self->memrefs, peek, ud);
exp = self->expressions;
max = rc_evaluate_expression(exp, peek, ud, L);

View File

@ -1,36 +0,0 @@
RC_SRC=../src/rcheevos
RC_URL_SRC=../src/rurl
LUA_SRC=lua/src
OBJ=$(RC_SRC)/trigger.o $(RC_SRC)/condset.o $(RC_SRC)/condition.o $(RC_SRC)/operand.o \
$(RC_SRC)/term.o $(RC_SRC)/expression.o $(RC_SRC)/value.o $(RC_SRC)/lboard.o \
$(RC_SRC)/alloc.o $(RC_SRC)/format.o \
$(RC_URL_SRC)/url.o \
$(LUA_SRC)/lapi.o $(LUA_SRC)/lcode.o $(LUA_SRC)/lctype.o $(LUA_SRC)/ldebug.o \
$(LUA_SRC)/ldo.o $(LUA_SRC)/ldump.o $(LUA_SRC)/lfunc.o $(LUA_SRC)/lgc.o $(LUA_SRC)/llex.o \
$(LUA_SRC)/lmem.o $(LUA_SRC)/lobject.o $(LUA_SRC)/lopcodes.o $(LUA_SRC)/lparser.o \
$(LUA_SRC)/lstate.o $(LUA_SRC)/lstring.o $(LUA_SRC)/ltable.o $(LUA_SRC)/ltm.o \
$(LUA_SRC)/lundump.o $(LUA_SRC)/lvm.o $(LUA_SRC)/lzio.o $(LUA_SRC)/lauxlib.o \
$(LUA_SRC)/lbaselib.o $(LUA_SRC)/lbitlib.o $(LUA_SRC)/lcorolib.o $(LUA_SRC)/ldblib.o \
$(LUA_SRC)/liolib.o $(LUA_SRC)/lmathlib.o $(LUA_SRC)/loslib.o $(LUA_SRC)/lstrlib.o \
$(LUA_SRC)/ltablib.o $(LUA_SRC)/lutf8lib.o $(LUA_SRC)/loadlib.o $(LUA_SRC)/linit.o \
test.o
all: test
%.o: %.c
gcc -Wall -O0 -g -std=c89 -ansi -Wno-long-long -DLUA_32BITS -I../include -I$(RC_SRC) -I$(LUA_SRC) -c $< -o $@
test: $(OBJ)
gcc -o $@ $+ -lm
test.o: smw_snes.h galaga_nes.h
smw_snes.h: smw_snes.json
xxd -i $< | sed "s@unsigned@const@" > $@
galaga_nes.h: galaga_nes.json
xxd -i $< | sed "s@unsigned@const@" > $@
clean:
rm -f test $(OBJ) smw_snes.h galaga_nes.h

View File

@ -1,205 +0,0 @@
{
"Success": true,
"PatchData": {
"ID": 1701,
"Title": "Galaga",
"ConsoleID": 7,
"ForumTopicID": 2528,
"Flags": 0,
"ImageIcon": "\/Images\/002324.png",
"ImageTitle": "\/Images\/002322.png",
"ImageIngame": "\/Images\/002323.png",
"ImageBoxArt": "\/Images\/012173.png",
"Publisher": "Bandai America (NA), Namco (JP)",
"Developer": "Namco",
"Genre": "Fixed Shooter",
"Released": "Nov 1988 (NA), Feb 1985 (JP)",
"IsFinal": false,
"ConsoleName": "NES",
"RichPresencePatch": null,
"Achievements": [{
"ID": 10055,
"MemAddr": "0xH0482=5",
"Title": "That Was Easy",
"Description": "Get to level 5.",
"Points": 5,
"Author": "dude1286",
"Modified": 1404761487,
"Created": 1404761423,
"BadgeName": "09723",
"Flags": 3
}, {
"ID": 10056,
"MemAddr": "0xH0481=1",
"Title": "Getting Slightly Difficult",
"Description": "Get to level 10.",
"Points": 20,
"Author": "dude1286",
"Modified": 1404761490,
"Created": 1404761427,
"BadgeName": "09724",
"Flags": 3
}, {
"ID": 10057,
"MemAddr": "0xH0481=2",
"Title": "Hail of Bullets",
"Description": "Get to level 20.",
"Points": 25,
"Author": "dude1286",
"Modified": 1404761493,
"Created": 1404761430,
"BadgeName": "09725",
"Flags": 3
}, {
"ID": 10058,
"MemAddr": "0xH0481=3",
"Title": "Bulletstorm",
"Description": "Get to level 30.",
"Points": 40,
"Author": "dude1286",
"Modified": 1404761498,
"Created": 1404761435,
"BadgeName": "09726",
"Flags": 3
}, {
"ID": 10059,
"MemAddr": "0xH0480=0_0xH0481=0_0xH0482=3_R:0xH0482!=3.1._0xH00c4=40",
"Title": "Challenge 1 Master",
"Description": "Get a perfect on Stage 3.",
"Points": 15,
"Author": "dude1286",
"Modified": 1404796406,
"Created": 1404761443,
"BadgeName": "09715",
"Flags": 3
}, {
"ID": 10060,
"MemAddr": "0xH0480=0_0xH0481=0_0xH0482=7_0xH00c4=40_R:0xH0482!=7.1.",
"Title": "Challenge 2 Master",
"Description": "Get a perfect on Stage 7.",
"Points": 20,
"Author": "dude1286",
"Modified": 1404796449,
"Created": 1404761447,
"BadgeName": "09716",
"Flags": 3
}, {
"ID": 10061,
"MemAddr": "0xH0480=0_0xH0481=1_0xH0482=1_R:0xH0482!=1.1._0xH00c4=40",
"Title": "Challenge 3 Master",
"Description": "Get a perfect on Stage 11.",
"Points": 25,
"Author": "dude1286",
"Modified": 1404796468,
"Created": 1404761450,
"BadgeName": "09717",
"Flags": 3
}, {
"ID": 10062,
"MemAddr": "0xH0480=0_0xH0481=1_0xH0482=5_R:0xH0482!=5.1._0xH00c4=40",
"Title": "Challenge 4 Master",
"Description": "Get a perfect on Stage 15.",
"Points": 30,
"Author": "dude1286",
"Modified": 1404796484,
"Created": 1404761454,
"BadgeName": "09718",
"Flags": 3
}, {
"ID": 10063,
"MemAddr": "0xH0480=0_0xH0481=1_0xH0482=9_R:0xH0482!=9.1._0xH00c4=40",
"Title": "Challenge 5 Master",
"Description": "Get a perfect on Stage 19.",
"Points": 35,
"Author": "dude1286",
"Modified": 1404796507,
"Created": 1404761457,
"BadgeName": "09719",
"Flags": 3
}, {
"ID": 10064,
"MemAddr": "0xH0480=0_0xH0481=2_0xH0482=3_R:0xH0482!=3.1._0xH00c4=40",
"Title": "Challenge 6 Master",
"Description": "Get a perfect on Stage 23.",
"Points": 40,
"Author": "dude1286",
"Modified": 1404796523,
"Created": 1404761461,
"BadgeName": "09720",
"Flags": 3
}, {
"ID": 10065,
"MemAddr": "0xH0480=0_0xH0481=2_0xH0482=7_R:0xH0482!=7.1._0xH00c4=40",
"Title": "Challenge 7 Master",
"Description": "Get a perfect on Stage 27.",
"Points": 45,
"Author": "dude1286",
"Modified": 1404796555,
"Created": 1404761464,
"BadgeName": "09721",
"Flags": 3
}, {
"ID": 10066,
"MemAddr": "0xH0480=0_0xH0481=3_0xH0482=1_R:0xH0482!=1.1._0xH00c4=40",
"Title": "Challenge 8 Master",
"Description": "Get a perfect on Stage 31.",
"Points": 50,
"Author": "dude1286",
"Modified": 1404796574,
"Created": 1404761468,
"BadgeName": "09722",
"Flags": 3
}, {
"ID": 10067,
"MemAddr": "0xH0079=4_d0xH0079=3",
"Title": "Was That On Purpose?",
"Description": "Get one of your ships captured by the enemy.",
"Points": 5,
"Author": "dude1286",
"Modified": 1404761532,
"Created": 1404761472,
"BadgeName": "09714",
"Flags": 3
}, {
"ID": 10068,
"MemAddr": "d0xH0079=6_0xH0079=1",
"Title": "Doubled Fire",
"Description": "Save a captured ship and have double the fire power.",
"Points": 10,
"Author": "dude1286",
"Modified": 1404761536,
"Created": 1404761476,
"BadgeName": "09713",
"Flags": 3
}, {
"ID": 10069,
"MemAddr": "0xH00e2>=3_d0xH00e2<3",
"Title": "Default Score",
"Description": "Get higher than the default hi-score.",
"Points": 10,
"Author": "dude1286",
"Modified": 1404761540,
"Created": 1404761479,
"BadgeName": "09727",
"Flags": 3
}, {
"ID": 10070,
"MemAddr": "0xH0482=2_d0xH0482=1_0xH04af=0xH04a7_0xH04ae=0xH04a6_0xH04ad=0xH04a5",
"Title": "Perfect Shot",
"Description": "Get to the second level without missing a shot.",
"Points": 25,
"Author": "dude1286",
"Modified": 1404761543,
"Created": 1404761482,
"BadgeName": "09712",
"Flags": 3
}],
"Leaderboards": [{
"ID": 310,
"Mem": "STA:0xh0482=1::CAN:0xh0470=0_0xh0471=0::SUB:0xh0485=0_d0xh007a=0_0xh007a=1::VAL:0xh00e5*10_0xh00e4*100_0xh00e3*1000_0xh00e2*10000_0xh00e1*100000_0xh00e0*1000000",
"Format": "SCORE",
"Title": "Hi-Score",
"Description": "Get the highest score possible."
}]
}
}

View File

@ -1,606 +0,0 @@
{
"Success": true,
"PatchData": {
"ID": 228,
"Title": "Super Mario World",
"ConsoleID": 3,
"ForumTopicID": 135,
"Flags": 0,
"ImageIcon": "\/Images\/006972.png",
"ImageTitle": "\/Images\/000021.png",
"ImageIngame": "\/Images\/000022.png",
"ImageBoxArt": "\/Images\/000138.png",
"Publisher": "Nintendo",
"Developer": "Nintendo EAD",
"Genre": "Platforming",
"Released": "JP 1990 , NA 1991 Europe 1992",
"IsFinal": false,
"ConsoleName": "SNES",
"RichPresencePatch": "Lookup:LevelName\r\n0x0=Title Screen\r\n0x14=Yellow Switch Palace\r\n0x28=Yoshi's House\r\n0x29=Yoshi's Island 1\r\n0x2a=Yoshi's Island 2\r\n0x27=Yoshi's Island 3\r\n0x26=Yoshi's Island 4\r\n0x25=#1 Iggy's Castle\r\n0x15=Donut Plains 1\r\n0x9=Donut Plains 2\r\n0x8=Green Switch Palace\r\n0x4=Donut Ghost House\r\n0x3=Top Secret Area\r\n0x5=Donut Plains 3\r\n0x6=Donut Plains 4\r\n0x7=#2 Morton's Castle\r\n0xa=Donut Secret 1\r\n0x13=Donut Secret House\r\n0x2f=Donut Secret 2\r\n0x3e=Vanilla Dome 1\r\n0x3c=Vanilla Dome 2\r\n0x3f=Red Switch Palace\r\n0x2b=Vanilla Ghost House\r\n0x2e=Vanilla Dome 3\r\n0x3d=Vanilla Dome 4\r\n0x40=#3 Lemmy's Castle\r\n0x2d=Vanilla Secret 1\r\n0x1=Vanilla Secret 2\r\n0x2=Vanilla Secret 3\r\n0xb=Vanilla Fortress\r\n0xc=Butter Bridge 1\r\n0xd=Butter Bridge 2\r\n0xe=#4 Ludwig's Castle\r\n0xf=Cheese Bridge Area\r\n0x10=Cookie Mountain\r\n0x11=Soda Lake\r\n0x41=Forest Ghost House\r\n0x42=Forest of Illusion 1\r\n0x43=Forest of Illusion 4\r\n0x44=Forest of Illusion 2\r\n0x45=Blue Switch Palace\r\n0x46=Forest Secret Area\r\n0x47=Forest of Illusion 3\r\n0x1f=Forest Fortress\r\n0x20=#5 Roy's Castle\r\n0x21=Choco-Ghost House\r\n0x22=Chocolate Island 1\r\n0x23=Chocolate Island 3\r\n0x24=Chocolate Island 2\r\n0x1b=Chocolate Fortress\r\n0x1d=Chocolate Island 4\r\n0x1c=Chocolate Island 5\r\n0x1a=#6 Wendy's Castle\r\n0x18=Sunken Ghost Ship\r\n0x3b=Chocolate Secret\r\n0x3a=Valley of Bowser 1\r\n0x39=Valley of Bowser 2\r\n0x38=Valley Ghost House\r\n0x37=Valley of Bowser 3\r\n0x33=Valley of Bowser 4\r\n0x34=#7 Larry's Castle\r\n0x35=Valley Fortress\r\n0x31=Front Door\r\n0x32=Back Door\r\n0x58=Star World 1\r\n0x54=Star World 2\r\n0x56=Star World 3\r\n0x59=Star World 4\r\n0x5a=Star World 5\r\n0x4e=Gnarly\r\n0x4f=Tubular\r\n0x50=Way Cool\r\n0x51=Awesome\r\n0x4c=Groovy\r\n0x4b=Mondo\r\n0x4a=Outrageous\r\n0x49=Funky\r\n\r\nFormat:Lives\r\nFormatType=VALUE\r\n\r\nDisplay:\r\n@LevelName(0xh0013bf), @Lives(0xh0dbe_v+1) lives",
"Achievements": [{
"ID": 4874,
"MemAddr": "0xH000019=2",
"Title": "I Believe I Can Fly",
"Description": "Collect a feather",
"Points": 2,
"Author": "UNHchabo",
"Modified": 1452548368,
"Created": 1391908064,
"BadgeName": "05506",
"Flags": 3
}, {
"ID": 4933,
"MemAddr": "0xH0018c2=1",
"Title": "Floating Through The Clouds",
"Description": "Hijack a Lakitu's cloud",
"Points": 2,
"Author": "UNHchabo",
"Modified": 1445779700,
"Created": 1392010935,
"BadgeName": "30357",
"Flags": 3
}, {
"ID": 341,
"MemAddr": "0x001420=5",
"Title": "Unleash The Dragon",
"Description": "Collect 5 Dragon Coins in a level",
"Points": 3,
"Author": "Scott",
"Modified": 1445783661,
"Created": 1367266583,
"BadgeName": "00549",
"Flags": 3
}, {
"ID": 342,
"MemAddr": "0xH000dc1=1_0xH0013bf>0",
"Title": "Giddy Up!",
"Description": "Catch a ride with a friend",
"Points": 2,
"Author": "Scott",
"Modified": 1445754183,
"Created": 1367266931,
"BadgeName": "00550",
"Flags": 3
}, {
"ID": 340,
"MemAddr": "0xH000dbf=99",
"Title": "Rich Mario",
"Description": "Collect 99 coins",
"Points": 5,
"Author": "Scott",
"Modified": 1445757056,
"Created": 1367254976,
"BadgeName": "00547",
"Flags": 3
}, {
"ID": 1706,
"MemAddr": "0xH001900=80",
"Title": "Maximum Finish",
"Description": "Cross the finish line at the end of the stage and collect the max 50 stars",
"Points": 10,
"Author": "jackolantern",
"Modified": 1372762549,
"Created": 1372674230,
"BadgeName": "02014",
"Flags": 3
}, {
"ID": 2246,
"MemAddr": "0xH000f31=0.20._R:0xH000f31!=0_0xH000f32=0.20._R:0xH000f32!=0_0xH000f33=0.20._R:0xH000f33!=0_0xH000dbe>d0xH000dbe.8._0xH001411=1.20._R:0xH001411=0",
"Title": "Perfect Bonus Stage",
"Description": "Score 8 extra lives in the 'Bonus Game'",
"Points": 10,
"Author": "Jaarl",
"Modified": 1445783578,
"Created": 1376582613,
"BadgeName": "02739",
"Flags": 3
}, {
"ID": 2199,
"MemAddr": "0xH001f28=1_0xH001f27=1_0xH001f29=1_0xH001f2a=1",
"Title": "Filling All The Blocks In",
"Description": "Hit the buttons in all four coloured switch palaces",
"Points": 10,
"Author": "jackolantern",
"Modified": 1445756980,
"Created": 1376514114,
"BadgeName": "02720",
"Flags": 3
}, {
"ID": 2253,
"MemAddr": "0xH0013bf=37_0xH000dd5=1",
"Title": "Iggy Koopa",
"Description": "Defeat Iggy Koopa of Castle #1",
"Points": 5,
"Author": "Jaarl",
"Modified": 1445751693,
"Created": 1376616356,
"BadgeName": "00562",
"Flags": 3
}, {
"ID": 347,
"MemAddr": "0xH0013bf=7_0xH000dd5=1",
"Title": "Morton Koopa Jr.",
"Description": "Defeat Morton Koopa Jr. of Castle #2",
"Points": 5,
"Author": "Scott",
"Modified": 1445783647,
"Created": 1367322700,
"BadgeName": "00562",
"Flags": 3
}, {
"ID": 2261,
"MemAddr": "0xH0013bf=64_0xH000dd5=1",
"Title": "Lemmy Koopa",
"Description": "Defeat Lemmy Koopa of Castle #3",
"Points": 10,
"Author": "Jaarl",
"Modified": 1425959153,
"Created": 1376652522,
"BadgeName": "00562",
"Flags": 3
}, {
"ID": 2262,
"MemAddr": "0xH0013bf=14_0xH000dd5=1",
"Title": "Ludwig von Koopa",
"Description": "Defeat Ludwig von Koopa of Castle #4",
"Points": 10,
"Author": "Jaarl",
"Modified": 1425959133,
"Created": 1376653163,
"BadgeName": "00562",
"Flags": 3
}, {
"ID": 2306,
"MemAddr": "0xH0013bf=32_0xH000dd5=1",
"Title": "Roy Koopa",
"Description": "Defeat Roy Koopa of Castle #5",
"Points": 10,
"Author": "Jaarl",
"Modified": 1425956637,
"Created": 1376938808,
"BadgeName": "00562",
"Flags": 3
}, {
"ID": 2309,
"MemAddr": "0xH0013bf=26_0xH000906=1.400._R:0xH0013bf!=26",
"Title": "Wendy O. Koopa",
"Description": "Defeat Wendy O. Koopa of Castle #6",
"Points": 10,
"Author": "Jaarl",
"Modified": 1390938088,
"Created": 1376939582,
"BadgeName": "00562",
"Flags": 3
}, {
"ID": 2342,
"MemAddr": "0xH0013bf=52_0xH000dd5=1",
"Title": "Larry Koopa",
"Description": "Defeat Larry Koopa of Castle #7",
"Points": 10,
"Author": "Jaarl",
"Modified": 1425959095,
"Created": 1376970283,
"BadgeName": "00562",
"Flags": 3
}, {
"ID": 2250,
"MemAddr": "0xH0013bf=11(20)_0xH000906=1(20)_R:0xH001411!=1",
"Title": "Reznor",
"Description": "Defeat the Reznor atop Vanilla Dome",
"Points": 10,
"Author": "Jaarl",
"Modified": 1376615087,
"Created": 1376615073,
"BadgeName": "02742",
"Flags": 3
}, {
"ID": 2307,
"MemAddr": "0xH0013bf=31(20)_0xH000906=1(20)_R:0xH001411!=1",
"Title": "Reznor Again?",
"Description": "Defeat the Reznor in the clearing of the Forest of Illusion",
"Points": 10,
"Author": "Jaarl",
"Modified": 1376938847,
"Created": 1376938811,
"BadgeName": "02742",
"Flags": 3
}, {
"ID": 2308,
"MemAddr": "0xH0013bf=27.20._0xH000906=1.20._R:0xH001411!=1",
"Title": "Reznor, Do You Ever Give Up?",
"Description": "Defeat the Reznor at the center of Chocolate Island",
"Points": 10,
"Author": "Jaarl",
"Modified": 1445751771,
"Created": 1376938815,
"BadgeName": "02742",
"Flags": 3
}, {
"ID": 2338,
"MemAddr": "0xH0013bf=53.20._0xH000906=1.20._R:0xH001411!=1",
"Title": "Reznor...",
"Description": "Defeat the Reznor in the Valley of Bowser",
"Points": 10,
"Author": "Jaarl",
"Modified": 1445783707,
"Created": 1376969412,
"BadgeName": "02742",
"Flags": 3
}, {
"ID": 2275,
"MemAddr": "0xH0013bf=49_R:0xH0013bf!=49_0xH0013f9=3_R:0xH0013f9!=3_0xH0013ef=1_R:0xH0013ef!=1",
"Title": "King Bowser Koopa",
"Description": "Beat Bowser and save the princess (Front Door!)",
"Points": 10,
"Author": "Jaarl",
"Modified": 1445783312,
"Created": 1376742802,
"BadgeName": "02764",
"Flags": 3
}, {
"ID": 2276,
"MemAddr": "0xH0013bf=49_R:0xH0013bf!=49_0xH0013f9=3_R:0xH0013f9!=3_0xH0013ef=1_R:0xH0013ef!=1_0xH000019=0_R:0xH000019!=0",
"Title": "Baby's First Kiss",
"Description": "Get the princess kiss as Little Mario (Front Door!)",
"Points": 5,
"Author": "Jaarl",
"Modified": 1445783313,
"Created": 1376742805,
"BadgeName": "02765",
"Flags": 3
}, {
"ID": 2277,
"MemAddr": "0xH0013bf=49_R:0xH0013bf!=49_0xH0013f9=3_R:0xH0013f9!=3_0xH0013ef=1_R:0xH0013ef!=1_0xH000019=3_R:0xH000019!=3",
"Title": "Burning Bowser",
"Description": "Get the princess kiss as Fire Mario (Front Door!)",
"Points": 5,
"Author": "Jaarl",
"Modified": 1445783314,
"Created": 1376742808,
"BadgeName": "02766",
"Flags": 3
}, {
"ID": 2278,
"MemAddr": "0xH0013bf=49_R:0xH0013bf!=49_0xH0013f9=3_R:0xH0013f9!=3_0xH0013ef=1_R:0xH0013ef!=1_0xH000019=2_R:0xH000019!=2",
"Title": "Flying Finish",
"Description": "Get the princess kiss as Cape Mario (Front Door!)",
"Points": 5,
"Author": "Jaarl",
"Modified": 1445783315,
"Created": 1376742811,
"BadgeName": "02767",
"Flags": 3
}, {
"ID": 2299,
"MemAddr": "0xH000020=168_R:0xH000020!=168_0xH00001e=248_R:0xH00001e!=248_0xH0013c3=0_R:0xH0013c3!=0_0xH0013bf=19_R:0xH0013bf!=19_0xH001411=0",
"Title": "The Big Boo",
"Description": "Defeat the Big Boo in Donut Secret House",
"Points": 5,
"Author": "Jaarl",
"Modified": 1445751707,
"Created": 1376918022,
"BadgeName": "02797",
"Flags": 3
}, {
"ID": 2298,
"MemAddr": "0xH0013c3=6",
"Title": "To the Stars!",
"Description": "Reach the Star Road",
"Points": 5,
"Author": "Jaarl",
"Modified": 1445751709,
"Created": 1376918019,
"BadgeName": "02798",
"Flags": 3
}, {
"ID": 2264,
"MemAddr": "0xH0013c3=3_R:0xH0013c3!=3_0xH001411=0_0xH000007>112_0xH000007<128_0xH000008>112_0xH000008<128",
"Title": "I Could've Sworn...",
"Description": "Get lost in the Forest of Illusion",
"Points": 3,
"Author": "Jaarl",
"Modified": 1445751711,
"Created": 1376657732,
"BadgeName": "02753",
"Flags": 3
}, {
"ID": 2305,
"MemAddr": "0xH00001e=169_0xH000020=28_0xH0013c3=0_0xH001411=0",
"Title": "Chocolate Donut",
"Description": "Walk in a circle on Chocolate Island",
"Points": 3,
"Author": "Jaarl",
"Modified": 1445754204,
"Created": 1376938805,
"BadgeName": "02806",
"Flags": 3
}, {
"ID": 2300,
"MemAddr": "0xH0013c3=5",
"Title": "Mario's Special Place",
"Description": "Get to the challenging Special Zone",
"Points": 10,
"Author": "Jaarl",
"Modified": 1445783441,
"Created": 1376918026,
"BadgeName": "02800",
"Flags": 3
}, {
"ID": 2302,
"MemAddr": "0xH0013c3=5(1)_0xH0013c3=1(1)_R:0xH0013c3=6_R:0xH0013c3=0_R:0xH001f79=0",
"Title": "Change of Scenery",
"Description": "Clear the Special Zone and change the seasons in Mushroom Kingdom",
"Points": 10,
"Author": "Jaarl",
"Modified": 1376929315,
"Created": 1376929303,
"BadgeName": "02803",
"Flags": 3
}, {
"ID": 2252,
"MemAddr": "0xH0013f3=1.20._0xH001411=1.20._R:0xH001411=0_0xH000019=0.20._R:0xH000019!=0.20.",
"Title": "Too Much Pasta",
"Description": "Let Little Mario load up on mama Luigi's Famous P(asta)-gas!",
"Points": 5,
"Author": "Jaarl",
"Modified": 1445751717,
"Created": 1376615082,
"BadgeName": "02744",
"Flags": 3
}, {
"ID": 2251,
"MemAddr": "0xH0013f3=1.20._0xH001411=1.20._R:0xH001411=0_0xH000019!=0_R:0xH000019=0",
"Title": "Another Kind of Flying",
"Description": "Send Mario flying with P-gas",
"Points": 5,
"Author": "Jaarl",
"Modified": 1445751754,
"Created": 1376615078,
"BadgeName": "02743",
"Flags": 3
}, {
"ID": 2263,
"MemAddr": "0xH001697=12_0xH0013bf=66_R:0xH001697=0",
"Title": "Bother The Wigglers",
"Description": "Jump on yellow Wigglers in Forest of Illusion 12 times in a row for a surprise!",
"Points": 10,
"Author": "Jaarl",
"Modified": 1445751796,
"Created": 1376655155,
"BadgeName": "02752",
"Flags": 3
}, {
"ID": 2274,
"MemAddr": "0xH0013bf=49_R:0xH0013bf!=49_0xH0013f9=3_R:0xH0013f9!=3_0xH001f2e=11_R:0xH001f2e!=11_0xH0013ef=1_R:0xH0013ef!=1",
"Title": "Shortest Route",
"Description": "Clear the fewest stages possible and beat the game",
"Points": 10,
"Author": "Jaarl",
"Modified": 1376742834,
"Created": 1376742799,
"BadgeName": "02768",
"Flags": 3
}, {
"ID": 2297,
"MemAddr": "0xH001f2e=0.1._0xH001f2e=1.1._0xH001f2e=2.1._0xH001f2e=3.1._0xH001f2e=4.1._0xH001f2e=5.1._0xH001f2e=6.1._0xH001f2e=7.1._0xH001f2e=8.1._0xH001f2e=9.1._0xH001f2e=10.1._0xH001f2e=11.1._0xH0013f9=3_R:0xH000dbe<d0xH000dbe_0xH0013bf=49_R:0xH001f79=0_R:0xH001f2e<d0xH001f2e_0xH0013ef=1",
"Title": "Starman Challenge",
"Description": "Clear the game without dying (One session)",
"Points": 20,
"Author": "Jaarl",
"Modified": 1438387321,
"Created": 1376918015,
"BadgeName": "02772",
"Flags": 3
}, {
"ID": 2345,
"MemAddr": "0xH0013ef=1_0xH0013f9=3_0xH0013bf=50",
"Title": "Backdooring Bowser",
"Description": "Beat Bowser through the Back Door",
"Points": 10,
"Author": "Jaarl",
"Modified": 1390856810,
"Created": 1376973534,
"BadgeName": "02842",
"Flags": 3
}, {
"ID": 2304,
"MemAddr": "0xH001f2e=96.1._0xH001f2e=95.1.",
"Title": "All Exits",
"Description": "100% clear the game",
"Points": 25,
"Author": "Jaarl",
"Modified": 1445783357,
"Created": 1376929308,
"BadgeName": "30364",
"Flags": 3
}, {
"ID": 2303,
"MemAddr": "R:0xH001411=1_R:0xH0013c3!=5_0xH0013c3=5.7200.",
"Title": "That Oh-So-Familiar Tune",
"Description": "Find the secret in the Special Zone",
"Points": 5,
"Author": "Jaarl",
"Modified": 1445751746,
"Created": 1376929305,
"BadgeName": "02804",
"Flags": 3
}, {
"ID": 2985,
"MemAddr": "0x0018f2=3598_0xH0013bf=31",
"Title": "The Investigator",
"Description": "Access a secret area in the Forest Fortress",
"Points": 10,
"Author": "mrvsonic87",
"Modified": 1445783367,
"Created": 1379656738,
"BadgeName": "03447",
"Flags": 3
}, {
"ID": 29653,
"MemAddr": "0xS001f34=1_0xR001f34=1_0xM001f33=1_0xN001f33=1_0xH000008!=85",
"Title": "Birth of Economy",
"Description": "Collect 5 Dragon Coins in all eligible levels in Yoshi's Island",
"Points": 5,
"Author": "Dexterspet",
"Modified": 1445754043,
"Created": 1445754019,
"BadgeName": "30332",
"Flags": 3
}, {
"ID": 29654,
"MemAddr": "0xS001f30=1_0xO001f31=1_0xR001f30=1_0xO001f2f=1_0xN001f2f=1_0xM001f34=1_0xH000008!=85",
"Title": "A Hole In Your Wallet",
"Description": "Collect 5 Dragon Coins in all eligible levels in Donut Plains",
"Points": 10,
"Author": "Dexterspet",
"Modified": 1445783890,
"Created": 1445754021,
"BadgeName": "30333",
"Flags": 3
}, {
"ID": 29655,
"MemAddr": "0xN001f36=1_0xP001f36=1_0xQ001f34=1_0xN001f34=1_0xO001f36=1_0xO001f34=1_0xS001f2f=1_0xR001f2f=1_0xH000008!=85",
"Title": "Like A Giant Bank",
"Description": "Collect 5 Dragon Coins in all eligible levels in Vanilla Dome",
"Points": 10,
"Author": "Dexterspet",
"Modified": 1445754045,
"Created": 1445754022,
"BadgeName": "30337",
"Flags": 3
}, {
"ID": 29656,
"MemAddr": "0xM001f30=1_0xT001f31=1_0xS001f31=1_0xP001f30=1_0xO001f30=1_0xH000008!=85",
"Title": "Economic Gaps",
"Description": "Collect 5 Dragon Coins in all eligible levels in Twin Bridges",
"Points": 10,
"Author": "Dexterspet",
"Modified": 1445754047,
"Created": 1445754023,
"BadgeName": "30338",
"Flags": 3
}, {
"ID": 29657,
"MemAddr": "0xP001f37=1_0xM001f37=1_0xS001f37=1_0xQ001f37=1_0xN001f37=1_0xT001f33=1_0xH000008!=85",
"Title": "Illusions of Grandeur",
"Description": "Collect 5 Dragon Coins in all eligible levels in the Forest of Illusion",
"Points": 10,
"Author": "Dexterspet",
"Modified": 1445754048,
"Created": 1445754024,
"BadgeName": "30339",
"Flags": 3
}, {
"ID": 29658,
"MemAddr": "0xR001f33=1_0xP001f33=1_0xQ001f33=1_0xO001f32=1_0xP001f32=1_0xT001f32=1_0xH000008!=85",
"Title": "Sweet Greed",
"Description": "Collect 5 Dragon Coins in all eligible levels in Chocolate Island",
"Points": 10,
"Author": "Dexterspet",
"Modified": 1445754049,
"Created": 1445754025,
"BadgeName": "30341",
"Flags": 3
}, {
"ID": 29659,
"MemAddr": "0xR001f36=1_0xS001f36=1_0xT001f36=1_0xM001f35=1_0xP001f35=1_0xH000008!=85",
"Title": "The Dragon's Hoard",
"Description": "Collect 5 Dragon Coins in all eligible levels in the Valley of Bowser",
"Points": 10,
"Author": "Dexterspet",
"Modified": 1445783722,
"Created": 1445754026,
"BadgeName": "30342",
"Flags": 3
}, {
"ID": 29660,
"MemAddr": "0xT001f3a=1_0xN001f38=1_0xM001f38=1_0xT001f39=1_0xS001f39=1_0xP001f38=1_0xQ001f38=1_0xR001f38=1_0xS001f38=1_0xH000008!=85",
"Title": "Special Sorta Person",
"Description": "Collect 5 Dragon Coins in all eligible levels in Special Zone and Star Road",
"Points": 15,
"Author": "Dexterspet",
"Modified": 1445783747,
"Created": 1445754027,
"BadgeName": "30343",
"Flags": 3
}, {
"ID": 29661,
"MemAddr": "0xS001ff3=1_0xH0013bf=41",
"Title": "Super Moonio",
"Description": "Collect the 3-Up Moon in Yoshi's Island",
"Points": 2,
"Author": "Dexterspet",
"Modified": 1445754053,
"Created": 1445754028,
"BadgeName": "30354",
"Flags": 3
}, {
"ID": 29662,
"MemAddr": "0xN001fee=1_0xH0013bf=6",
"Title": "Crescent Donut",
"Description": "Collect the 3-Up Moon in Donut Plains",
"Points": 2,
"Author": "Dexterspet",
"Modified": 1445754054,
"Created": 1445754029,
"BadgeName": "30345",
"Flags": 3
}, {
"ID": 29663,
"MemAddr": "0xN001ff3=1_0xH0013bf=46",
"Title": "Lunar Vanilla",
"Description": "Collect the 3-Up Moon in Vanilla Dome",
"Points": 3,
"Author": "Dexterspet",
"Modified": 1445754055,
"Created": 1445754031,
"BadgeName": "30356",
"Flags": 3
}, {
"ID": 29664,
"MemAddr": "0xM001fef=1_0xH0013bf=15",
"Title": "Bridge Over Moonlit Water",
"Description": "Collect the 3-Up Moon in Twin Bridges",
"Points": 2,
"Author": "Dexterspet",
"Modified": 1445754057,
"Created": 1445754032,
"BadgeName": "30355",
"Flags": 3
}, {
"ID": 29665,
"MemAddr": "0xS001ff6=1_0xH0013bf=65",
"Title": "A False Moon",
"Description": "Collect the 3-Up Moon in the Forest of Illusion",
"Points": 2,
"Author": "Dexterspet",
"Modified": 1445783378,
"Created": 1445754033,
"BadgeName": "30349",
"Flags": 3
}, {
"ID": 29666,
"MemAddr": "0xR001ff2=1_0xH0013bf=34",
"Title": "Lunaddiction",
"Description": "Collect the 3-Up Moon in Chocolate Island",
"Points": 2,
"Author": "Dexterspet",
"Modified": 1445754059,
"Created": 1445754035,
"BadgeName": "30350",
"Flags": 3
}, {
"ID": 29667,
"MemAddr": "0xR001ff5=1_0xH0013bf=58",
"Title": "Under A Koopa Moon",
"Description": "Collect the 3-Up Moon in the Valley of Bowser",
"Points": 2,
"Author": "Dexterspet",
"Modified": 1445783716,
"Created": 1445754036,
"BadgeName": "30351",
"Flags": 3
}],
"Leaderboards": []
}
}

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,7 @@
#ifdef HAVE_CHEEVOS
#include "../cheevos/cheevos.h"
#include "../cheevos-new/cheevos.h" /* RCHEEVOS TODO: remove line */
#endif
#ifdef HAVE_MENU

View File

@ -37,6 +37,7 @@
#ifdef HAVE_CHEEVOS
#include "cheevos/cheevos.h"
#include "cheevos-new/cheevos.h" /* RCHEEVOS TODO: remove line */
#endif
#ifdef HAVE_OPENGL
@ -1924,7 +1925,8 @@ bool rarch_environment_cb(unsigned cmd, void *data)
{
bool state = *(const bool*)data;
RARCH_LOG("Environ SET_SUPPORT_ACHIEVEMENTS: %s.\n", state ? "yes" : "no");
cheevos_set_support_cheevos(state);
/* RCHEEVOS TODO: remove settings test */
settings->bools.cheevos_rcheevos_enable ? rcheevos_set_support_cheevos(state) : cheevos_set_support_cheevos(state);
}
#endif
break;

View File

@ -158,9 +158,12 @@ ACHIEVEMENTS
#include "../libretro-common/formats/json/jsonsax.c"
#include "../network/net_http_special.c"
#ifdef HAVE_NEW_CHEEVOS
#include "../cheevos/cheevos.c"
#include "../cheevos/badges.c"
#include "../cheevos/cond.c"
#include "../cheevos/var.c"
#include "../cheevos-new/cheevos.c"
#include "../cheevos-new/badges.c"
#include "../cheevos-new/fixup.c"
#include "../cheevos-new/hash.c"
#include "../cheevos-new/parser.c"
@ -175,13 +178,9 @@ ACHIEVEMENTS
#include "../deps/rcheevos/src/rcheevos/term.c"
#include "../deps/rcheevos/src/rcheevos/trigger.c"
#include "../deps/rcheevos/src/rcheevos/value.c"
#include "../deps/rcheevos/src/rcheevos/memref.c"
#include "../deps/rcheevos/src/rcheevos/richpresence.c"
#include "../deps/rcheevos/src/rurl/url.c"
#else
#include "../cheevos/cheevos.c"
#include "../cheevos/badges.c"
#include "../cheevos/cond.c"
#include "../cheevos/var.c"
#endif
#endif

View File

@ -41,6 +41,7 @@
#ifdef HAVE_CHEEVOS
#include "../cheevos/cheevos.h"
#include "../cheevos-new/cheevos.h" /* RCHEEVOS TODO: remove line */
#endif
#include "cheat_manager.h"
@ -68,7 +69,10 @@ unsigned cheat_manager_get_size(void)
void cheat_manager_apply_cheats(void)
{
#ifdef HAVE_CHEEVOS
bool data_bool = false;
/* RCHEEVOS TODO: remove settings init */
settings_t *settings = config_get_ptr();
bool data_bool = false;
#endif
unsigned i, idx = 0;
@ -100,7 +104,8 @@ void cheat_manager_apply_cheats(void)
#ifdef HAVE_CHEEVOS
data_bool = idx != 0;
cheevos_apply_cheats(&data_bool);
/* RCHEEVOS TODO: remove settings test */
settings->bools.cheevos_rcheevos_enable ? rcheevos_apply_cheats(&data_bool) : cheevos_apply_cheats(&data_bool);
#endif
}

View File

@ -78,6 +78,7 @@
#ifdef HAVE_CHEEVOS
#include "../cheevos/cheevos.h"
#include "../cheevos-new/cheevos.h" /* RCHEEVOS TODO: remove line */
#endif
#include "../../record/record_driver.h"

View File

@ -21,6 +21,7 @@
#ifdef HAVE_CHEEVOS
#include "../../cheevos/cheevos.h"
#include "../../cheevos-new/cheevos.h" /* RCHEEVOS TODO: remove line */
#endif
#include "../../verbosity.h"
@ -588,12 +589,14 @@ static int action_bind_sublabel_cheevos_entry(
char *s, size_t len)
{
#ifdef HAVE_CHEEVOS
settings_t *settings = config_get_ptr(); /* RCHEEVOS TODO: remove line */
cheevos_ctx_desc_t desc_info;
unsigned new_id = type - MENU_SETTINGS_CHEEVOS_START;
desc_info.idx = new_id;
desc_info.s = s;
desc_info.len = len;
cheevos_get_description(&desc_info);
/* RCHEEVOS TODO: remove test */
settings->bools.cheevos_rcheevos_enable ? rcheevos_get_description((rcheevos_ctx_desc_t*) &desc_info) : cheevos_get_description(&desc_info);
strlcpy(s, desc_info.s, len);
#endif

View File

@ -39,6 +39,7 @@
#ifdef HAVE_CHEEVOS
#include "../cheevos/cheevos.h"
#include "../cheevos-new/cheevos.h" /* RCHEEVOS TODO: remove line */
#endif
#ifdef HAVE_NETWORKING
@ -2667,7 +2668,8 @@ static int menu_displaylist_parse_load_content_settings(
if (settings->bools.quick_menu_show_save_load_state
#ifdef HAVE_CHEEVOS
&& !cheevos_hardcore_active
/* RCHEEVOS TODO: remove 'rcheevos_*' below */
&& !(rcheevos_hardcore_active || cheevos_hardcore_active)
#endif
)
{
@ -2690,7 +2692,8 @@ static int menu_displaylist_parse_load_content_settings(
if (settings->bools.quick_menu_show_save_load_state &&
settings->bools.quick_menu_show_undo_save_load_state
#ifdef HAVE_CHEEVOS
&& !cheevos_hardcore_active
/* RCHEEVOS TODO: remove 'rcheevos_*' below */
&& !(rcheevos_hardcore_active || cheevos_hardcore_active)
#endif
)
{
@ -5564,10 +5567,13 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist
break;
case DISPLAYLIST_ACHIEVEMENT_LIST:
#ifdef HAVE_CHEEVOS
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
cheevos_populate_menu(info);
info->need_push = true;
info->need_refresh = true;
{ /* RCHEEVOS TODO: remove brackets, settings and settings test */
settings_t *settings = config_get_ptr();
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
settings->bools.cheevos_rcheevos_enable ? rcheevos_populate_menu(info) : cheevos_populate_menu(info);
info->need_push = true;
info->need_refresh = true;
}
#endif
break;

View File

@ -50,6 +50,7 @@
#ifdef HAVE_CHEEVOS
#include "../cheevos/cheevos.h"
#include "../cheevos-new/cheevos.h" /* RCHEEVOS TODO: remove line */
#endif
#include "../frontend/frontend_driver.h"
@ -3609,7 +3610,8 @@ static void achievement_hardcore_mode_write_handler(rarch_setting_t *setting)
if (settings && settings->bools.cheevos_enable && settings->bools.cheevos_hardcore_mode_enable)
{
cheevos_toggle_hardcore_mode();
/* RCHEEVOS TODO: remove settings test */
settings->bools.cheevos_rcheevos_enable ? rcheevos_toggle_hardcore_mode() : cheevos_toggle_hardcore_mode();
command_event(CMD_EVENT_RESET, NULL);
return;
}

View File

@ -23,6 +23,7 @@
#ifdef HAVE_CHEEVOS
#include "../../cheevos/cheevos.h"
#include "../../cheevos-new/cheevos.h" /* RCHEEVOS TODO: remove line */
#endif
#include "menu_dialog.h"
@ -173,10 +174,14 @@ int menu_dialog_iterate(char *s, size_t len, const char *label)
#ifdef HAVE_CHEEVOS
case MENU_DIALOG_HELP_CHEEVOS_DESCRIPTION:
desc_info.idx = menu_dialog_current_id;
desc_info.s = s;
desc_info.len = len;
cheevos_get_description(&desc_info);
{ /* RCHEEVOS TODO: remove brackets, settings and settings test */
settings_t *settings = config_get_ptr();
desc_info.idx = menu_dialog_current_id;
desc_info.s = s;
desc_info.len = len;
settings->bools.cheevos_rcheevos_enable ? rcheevos_get_description((rcheevos_ctx_desc_t*) &desc_info) : cheevos_get_description(&desc_info);
}
break;
#endif

View File

@ -30,6 +30,7 @@
#include "../../gfx/video_driver.h"
#include "../../managers/core_option_manager.h"
#include "../../cheevos/cheevos.h"
#include "../../cheevos-new/cheevos.h" /* RCHEEVOS TODO: remove line */
#include "../../content.h"
#define BASIC_INFO "info"

View File

@ -121,8 +121,6 @@ HAVE_QT=auto # Qt companion support
C89_QT=no
HAVE_XSHM=no # XShm video driver support
HAVE_CHEEVOS=yes # Retro Achievements
HAVE_NEW_CHEEVOS=no # Use rcheevos to process RetroAchievements
C89_NEW_CHEEVOS=no
HAVE_LUA=no # Lua support (for Retro Achievements)
HAVE_DISCORD=yes # Discord Integration
C89_DISCORD=no

View File

@ -79,6 +79,7 @@
#ifdef HAVE_CHEEVOS
#include "cheevos/cheevos.h"
#include "cheevos-new/cheevos.h" /* RCHEEVOS TODO: remove line */
#endif
#ifdef HAVE_DISCORD
@ -3233,7 +3234,8 @@ bool runloop_msg_queue_pull(const char **ret)
*/
#define time_to_exit(quit_key_pressed) (runloop_shutdown_initiated || quit_key_pressed || !is_alive || bsv_movie_is_end_of_file() || ((runloop_max_frames != 0) && (frame_count >= runloop_max_frames)) || runloop_exec)
#define runloop_check_cheevos() (settings->bools.cheevos_enable && cheevos_loaded && (!cheats_are_enabled && !cheats_were_enabled))
/* RCHEEVOS TODO: remove 'rcheevos_*' tests below */
#define runloop_check_cheevos() (settings->bools.cheevos_enable && (rcheevos_loaded || cheevos_loaded) && (!(rcheevos_cheats_are_enabled || cheats_are_enabled) && !(rcheevos_cheats_were_enabled || cheats_were_enabled)))
#ifdef HAVE_NETWORKING
/* FIXME: This is an ugly way to tell Netplay this... */
@ -4129,17 +4131,18 @@ static enum runloop_state runloop_check_state(
}
#ifdef HAVE_CHEEVOS
cheevos_hardcore_active = settings->bools.cheevos_enable
/* RCHEEVOS TODO: remove the 'rcheevos_*' below */
rcheevos_hardcore_active = cheevos_hardcore_active = settings->bools.cheevos_enable
&& settings->bools.cheevos_hardcore_mode_enable
&& cheevos_loaded && !cheevos_hardcore_paused;
&& (rcheevos_loaded || cheevos_loaded) && !(rcheevos_hardcore_paused || cheevos_hardcore_paused);
if (cheevos_hardcore_active && cheevos_state_loaded_flag)
if ((rcheevos_hardcore_active || cheevos_hardcore_active) && (rcheevos_state_loaded_flag || cheevos_state_loaded_flag))
{
cheevos_hardcore_paused = true;
rcheevos_hardcore_paused = cheevos_hardcore_paused = true;
runloop_msg_queue_push(msg_hash_to_str(MSG_CHEEVOS_HARDCORE_MODE_DISABLED), 0, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
}
if (!cheevos_hardcore_active)
if (!(rcheevos_hardcore_active || cheevos_hardcore_active))
#endif
{
char s[128];
@ -4165,7 +4168,8 @@ static enum runloop_state runloop_check_state(
/* Checks if slowmotion toggle/hold was being pressed and/or held. */
#ifdef HAVE_CHEEVOS
if (!cheevos_hardcore_active)
/* RCHEEVOS TODO: remove the 'rcheevos_*' below */
if (!(rcheevos_hardcore_active || cheevos_hardcore_active))
#endif
{
static bool old_slowmotion_button_state = false;
@ -4521,8 +4525,8 @@ int runloop_iterate(unsigned *sleep_ms)
rarch_core_runtime_tick();
#ifdef HAVE_CHEEVOS
if (runloop_check_cheevos())
cheevos_test();
if (runloop_check_cheevos()) /* RCHEEVOS TODO: remove settings test */
settings->bools.cheevos_rcheevos_enable ? rcheevos_test() : cheevos_test();
#endif
cheat_manager_apply_retro_cheats();

View File

@ -71,6 +71,7 @@
#ifdef HAVE_CHEEVOS
#include "../cheevos/cheevos.h"
#include "../cheevos-new/cheevos.h" /* RCHEEVOS TODO: remove line */
#endif
#include "task_content.h"
@ -734,13 +735,15 @@ static bool content_file_load(
#ifdef HAVE_CHEEVOS
if (!special)
{
/* RCHEEVOS TODO: remove settings and settings tests */
settings_t *settings = config_get_ptr();
const char *content_path = content->elems[0].data;
enum rarch_content_type type = path_is_media_type(content_path);
cheevos_set_cheats();
settings->bools.cheevos_rcheevos_enable ? rcheevos_set_cheats() : cheevos_set_cheats();
if (type == RARCH_CONTENT_NONE && !string_is_empty(content_path))
cheevos_load(info);
settings->bools.cheevos_rcheevos_enable ? rcheevos_load(info) : cheevos_load(info);
}
#endif