mirror of
				https://github.com/RetroDECK/Duckstation.git
				synced 2025-04-10 19:15:14 +00:00 
			
		
		
		
	
		
			
	
	
		
			547 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			547 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | #ifndef RCHEEVOS_H
 | ||
|  | #define RCHEEVOS_H
 | ||
|  | 
 | ||
|  | #ifdef __cplusplus
 | ||
|  | extern "C" { | ||
|  | #endif
 | ||
|  | 
 | ||
|  | typedef struct lua_State lua_State; | ||
|  | 
 | ||
|  | /*****************************************************************************\
 | ||
|  | | Return values                                                               | | ||
|  | \*****************************************************************************/ | ||
|  | 
 | ||
|  | enum { | ||
|  |   RC_OK = 0, | ||
|  |   RC_INVALID_LUA_OPERAND = -1, | ||
|  |   RC_INVALID_MEMORY_OPERAND = -2, | ||
|  |   RC_INVALID_CONST_OPERAND = -3, | ||
|  |   RC_INVALID_FP_OPERAND = -4, | ||
|  |   RC_INVALID_CONDITION_TYPE = -5, | ||
|  |   RC_INVALID_OPERATOR = -6, | ||
|  |   RC_INVALID_REQUIRED_HITS = -7, | ||
|  |   RC_DUPLICATED_START = -8, | ||
|  |   RC_DUPLICATED_CANCEL = -9, | ||
|  |   RC_DUPLICATED_SUBMIT = -10, | ||
|  |   RC_DUPLICATED_VALUE = -11, | ||
|  |   RC_DUPLICATED_PROGRESS = -12, | ||
|  |   RC_MISSING_START = -13, | ||
|  |   RC_MISSING_CANCEL = -14, | ||
|  |   RC_MISSING_SUBMIT = -15, | ||
|  |   RC_MISSING_VALUE = -16, | ||
|  |   RC_INVALID_LBOARD_FIELD = -17, | ||
|  |   RC_MISSING_DISPLAY_STRING = -18, | ||
|  |   RC_OUT_OF_MEMORY = -19, | ||
|  |   RC_INVALID_VALUE_FLAG = -20, | ||
|  |   RC_MISSING_VALUE_MEASURED = -21, | ||
|  |   RC_MULTIPLE_MEASURED = -22, | ||
|  |   RC_INVALID_MEASURED_TARGET = -23, | ||
|  |   RC_INVALID_COMPARISON = -24, | ||
|  |   RC_INVALID_STATE = -25 | ||
|  | }; | ||
|  | 
 | ||
|  | const char* rc_error_str(int ret); | ||
|  | 
 | ||
|  | /*****************************************************************************\
 | ||
|  | | Callbacks                                                                   | | ||
|  | \*****************************************************************************/ | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * Callback used to read num_bytes bytes from memory starting at address. If | ||
|  |  * num_bytes is greater than 1, the value is read in little-endian from | ||
|  |  * memory. | ||
|  |  */ | ||
|  | typedef unsigned (*rc_peek_t)(unsigned address, unsigned num_bytes, void* ud); | ||
|  | 
 | ||
|  | /*****************************************************************************\
 | ||
|  | | Memory References                                                           | | ||
|  | \*****************************************************************************/ | ||
|  | 
 | ||
|  | /* Sizes. */ | ||
|  | enum { | ||
|  |   RC_MEMSIZE_8_BITS, | ||
|  |   RC_MEMSIZE_16_BITS, | ||
|  |   RC_MEMSIZE_24_BITS, | ||
|  |   RC_MEMSIZE_32_BITS, | ||
|  |   RC_MEMSIZE_LOW, | ||
|  |   RC_MEMSIZE_HIGH, | ||
|  |   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_BITCOUNT, | ||
|  |   RC_MEMSIZE_VARIABLE | ||
|  | }; | ||
|  | 
 | ||
|  | typedef struct rc_memref_value_t { | ||
|  |   /* The current value of this memory reference. */ | ||
|  |   unsigned value; | ||
|  |   /* The last differing value of this memory reference. */ | ||
|  |   unsigned prior; | ||
|  | 
 | ||
|  |   /* The size of the value. */ | ||
|  |   char size; | ||
|  |   /* True if the value changed this frame. */ | ||
|  |   char changed; | ||
|  |   /* True if the reference will be used in indirection.
 | ||
|  |    * NOTE: This is actually a property of the rc_memref_t, but we put it here to save space */ | ||
|  |   char is_indirect; | ||
|  | } rc_memref_value_t; | ||
|  | 
 | ||
|  | typedef struct rc_memref_t rc_memref_t; | ||
|  | 
 | ||
|  | struct rc_memref_t { | ||
|  |   /* The current value at the specified memory address. */ | ||
|  |   rc_memref_value_t value; | ||
|  | 
 | ||
|  |   /* The memory address of this variable. */ | ||
|  |   unsigned address; | ||
|  | 
 | ||
|  |   /* The next memory reference in the chain. */ | ||
|  |   rc_memref_t* next; | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | /*****************************************************************************\
 | ||
|  | | Operands                                                                    | | ||
|  | \*****************************************************************************/ | ||
|  | 
 | ||
|  | /* types */ | ||
|  | enum { | ||
|  |   RC_OPERAND_ADDRESS,        /* 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_PRIOR,          /* The last differing value at this address. */ | ||
|  |   RC_OPERAND_BCD,            /* The BCD-decoded value of a live address in RAM. */ | ||
|  |   RC_OPERAND_INVERTED        /* The twos-complement value of a live address in RAM. */ | ||
|  | }; | ||
|  | 
 | ||
|  | typedef struct { | ||
|  |   union { | ||
|  |     /* A value read from memory. */ | ||
|  |     rc_memref_t* memref; | ||
|  | 
 | ||
|  |     /* An integer value. */ | ||
|  |     unsigned num; | ||
|  | 
 | ||
|  |     /* A floating point value. */ | ||
|  |     double dbl; | ||
|  | 
 | ||
|  |     /* A reference to the Lua function that provides the value. */ | ||
|  |     int luafunc; | ||
|  |   } value; | ||
|  | 
 | ||
|  |   /* specifies which member of the value union is being used */ | ||
|  |   char type; | ||
|  | 
 | ||
|  |   /* the actual RC_MEMSIZE of the operand - memref.size may differ */ | ||
|  |   char size; | ||
|  | } | ||
|  | rc_operand_t; | ||
|  | 
 | ||
|  | /*****************************************************************************\
 | ||
|  | | Conditions                                                                  | | ||
|  | \*****************************************************************************/ | ||
|  | 
 | ||
|  | /* types */ | ||
|  | enum { | ||
|  |   RC_CONDITION_STANDARD, | ||
|  |   RC_CONDITION_PAUSE_IF, | ||
|  |   RC_CONDITION_RESET_IF, | ||
|  |   RC_CONDITION_ADD_SOURCE, | ||
|  |   RC_CONDITION_SUB_SOURCE, | ||
|  |   RC_CONDITION_ADD_HITS, | ||
|  |   RC_CONDITION_AND_NEXT, | ||
|  |   RC_CONDITION_MEASURED, | ||
|  |   RC_CONDITION_ADD_ADDRESS, | ||
|  |   RC_CONDITION_OR_NEXT, | ||
|  |   RC_CONDITION_TRIGGER, | ||
|  |   RC_CONDITION_MEASURED_IF, | ||
|  |   RC_CONDITION_RESET_NEXT_IF, | ||
|  |   RC_CONDITION_SUB_HITS | ||
|  | }; | ||
|  | 
 | ||
|  | /* operators */ | ||
|  | enum { | ||
|  |   RC_OPERATOR_EQ, | ||
|  |   RC_OPERATOR_LT, | ||
|  |   RC_OPERATOR_LE, | ||
|  |   RC_OPERATOR_GT, | ||
|  |   RC_OPERATOR_GE, | ||
|  |   RC_OPERATOR_NE, | ||
|  |   RC_OPERATOR_NONE, | ||
|  |   RC_OPERATOR_MULT, | ||
|  |   RC_OPERATOR_DIV, | ||
|  |   RC_OPERATOR_AND | ||
|  | }; | ||
|  | 
 | ||
|  | typedef struct rc_condition_t rc_condition_t; | ||
|  | 
 | ||
|  | struct rc_condition_t { | ||
|  |   /* The condition's operands. */ | ||
|  |   rc_operand_t operand1; | ||
|  |   rc_operand_t operand2; | ||
|  | 
 | ||
|  |   /* Required hits to fire this condition. */ | ||
|  |   unsigned required_hits; | ||
|  |   /* Number of hits so far. */ | ||
|  |   unsigned current_hits; | ||
|  | 
 | ||
|  |   /* The next condition in the chain. */ | ||
|  |   rc_condition_t* next; | ||
|  | 
 | ||
|  |   /* The type of the condition. */ | ||
|  |   char type; | ||
|  | 
 | ||
|  |   /* The comparison operator to use. */ | ||
|  |   char oper; /* operator is a reserved word in C++. */ | ||
|  | 
 | ||
|  |   /* Set if the condition needs to processed as part of the "check if paused" pass. */ | ||
|  |   char pause; | ||
|  | 
 | ||
|  |   /* Whether or not the condition evaluated true on the last check */ | ||
|  |   char is_true; | ||
|  | }; | ||
|  | 
 | ||
|  | /*****************************************************************************\
 | ||
|  | | Condition sets                                                              | | ||
|  | \*****************************************************************************/ | ||
|  | 
 | ||
|  | typedef struct rc_condset_t rc_condset_t; | ||
|  | 
 | ||
|  | struct rc_condset_t { | ||
|  |   /* The next condition set in the chain. */ | ||
|  |   rc_condset_t* next; | ||
|  | 
 | ||
|  |   /* The list of conditions in this condition set. */ | ||
|  |   rc_condition_t* conditions; | ||
|  | 
 | ||
|  |   /* True if any condition in the set is a pause condition. */ | ||
|  |   char has_pause; | ||
|  | 
 | ||
|  |   /* True if the set is currently paused. */ | ||
|  |   char is_paused; | ||
|  | }; | ||
|  | 
 | ||
|  | /*****************************************************************************\
 | ||
|  | | Trigger                                                                     | | ||
|  | \*****************************************************************************/ | ||
|  | 
 | ||
|  | enum { | ||
|  |   RC_TRIGGER_STATE_INACTIVE,   /* achievement is not being processed */ | ||
|  |   RC_TRIGGER_STATE_WAITING,    /* achievement cannot trigger until it has been false for at least one frame */ | ||
|  |   RC_TRIGGER_STATE_ACTIVE,     /* achievement is active and may trigger */ | ||
|  |   RC_TRIGGER_STATE_PAUSED,     /* achievement is currently paused and will not trigger */ | ||
|  |   RC_TRIGGER_STATE_RESET,      /* achievement hit counts were reset */ | ||
|  |   RC_TRIGGER_STATE_TRIGGERED,  /* achievement has triggered */ | ||
|  |   RC_TRIGGER_STATE_PRIMED,     /* all non-Trigger conditions are true */ | ||
|  |   RC_TRIGGER_STATE_DISABLED    /* achievement cannot be processed at this time */ | ||
|  | }; | ||
|  | 
 | ||
|  | typedef struct { | ||
|  |   /* The main condition set. */ | ||
|  |   rc_condset_t* requirement; | ||
|  | 
 | ||
|  |   /* The list of sub condition sets in this test. */ | ||
|  |   rc_condset_t* alternative; | ||
|  | 
 | ||
|  |   /* The memory references required by the trigger. */ | ||
|  |   rc_memref_t* memrefs; | ||
|  | 
 | ||
|  |   /* The current state of the MEASURED condition. */ | ||
|  |   unsigned measured_value; | ||
|  | 
 | ||
|  |   /* The target state of the MEASURED condition */ | ||
|  |   unsigned measured_target; | ||
|  | 
 | ||
|  |   /* The current state of the trigger */ | ||
|  |   char state; | ||
|  | 
 | ||
|  |   /* True if at least one condition has a non-zero hit count */ | ||
|  |   char has_hits; | ||
|  | 
 | ||
|  |   /* True if at least one condition has a non-zero required hit count */ | ||
|  |   char has_required_hits; | ||
|  | } | ||
|  | rc_trigger_t; | ||
|  | 
 | ||
|  | int rc_trigger_size(const char* memaddr); | ||
|  | rc_trigger_t* rc_parse_trigger(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx); | ||
|  | int rc_evaluate_trigger(rc_trigger_t* trigger, rc_peek_t peek, void* ud, lua_State* L); | ||
|  | int rc_test_trigger(rc_trigger_t* trigger, rc_peek_t peek, void* ud, lua_State* L); | ||
|  | void rc_reset_trigger(rc_trigger_t* self); | ||
|  | 
 | ||
|  | /*****************************************************************************\
 | ||
|  | | Values                                                                      | | ||
|  | \*****************************************************************************/ | ||
|  | 
 | ||
|  | typedef struct rc_value_t rc_value_t; | ||
|  | 
 | ||
|  | struct rc_value_t { | ||
|  |   /* The current value of the variable. */ | ||
|  |   rc_memref_value_t value; | ||
|  | 
 | ||
|  |   /* The list of conditions to evaluate. */ | ||
|  |   rc_condset_t* conditions; | ||
|  | 
 | ||
|  |   /* The memory references required by the value. */ | ||
|  |   rc_memref_t* memrefs; | ||
|  | 
 | ||
|  |   /* The name of the variable. */ | ||
|  |   const char* name; | ||
|  | 
 | ||
|  |   /* The next variable in the chain. */ | ||
|  |   rc_value_t* next; | ||
|  | }; | ||
|  | 
 | ||
|  | int rc_value_size(const char* memaddr); | ||
|  | rc_value_t* rc_parse_value(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx); | ||
|  | int rc_evaluate_value(rc_value_t* value, rc_peek_t peek, void* ud, lua_State* L); | ||
|  | 
 | ||
|  | /*****************************************************************************\
 | ||
|  | | Leaderboards                                                                | | ||
|  | \*****************************************************************************/ | ||
|  | 
 | ||
|  | /* Return values for rc_evaluate_lboard. */ | ||
|  | enum { | ||
|  |   RC_LBOARD_STATE_INACTIVE,  /* leaderboard is not being processed */ | ||
|  |   RC_LBOARD_STATE_WAITING,   /* leaderboard cannot activate until the start condition has been false for at least one frame */ | ||
|  |   RC_LBOARD_STATE_ACTIVE,    /* leaderboard is active and may start */ | ||
|  |   RC_LBOARD_STATE_STARTED,   /* leaderboard attempt in progress */ | ||
|  |   RC_LBOARD_STATE_CANCELED,  /* leaderboard attempt canceled */ | ||
|  |   RC_LBOARD_STATE_TRIGGERED, /* leaderboard attempt complete, value should be submitted */ | ||
|  |   RC_LBOARD_STATE_DISABLED   /* leaderboard cannot be processed at this time */ | ||
|  | }; | ||
|  | 
 | ||
|  | typedef struct { | ||
|  |   rc_trigger_t start; | ||
|  |   rc_trigger_t submit; | ||
|  |   rc_trigger_t cancel; | ||
|  |   rc_value_t value; | ||
|  |   rc_value_t* progress; | ||
|  |   rc_memref_t* memrefs; | ||
|  | 
 | ||
|  |   char state; | ||
|  | } | ||
|  | rc_lboard_t; | ||
|  | 
 | ||
|  | int rc_lboard_size(const char* memaddr); | ||
|  | rc_lboard_t* rc_parse_lboard(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx); | ||
|  | int rc_evaluate_lboard(rc_lboard_t* lboard, int* value, rc_peek_t peek, void* peek_ud, lua_State* L); | ||
|  | void rc_reset_lboard(rc_lboard_t* lboard); | ||
|  | 
 | ||
|  | /*****************************************************************************\
 | ||
|  | | Value formatting                                                            | | ||
|  | \*****************************************************************************/ | ||
|  | 
 | ||
|  | /* Supported formats. */ | ||
|  | enum { | ||
|  |   RC_FORMAT_FRAMES, | ||
|  |   RC_FORMAT_SECONDS, | ||
|  |   RC_FORMAT_CENTISECS, | ||
|  |   RC_FORMAT_SCORE, | ||
|  |   RC_FORMAT_VALUE, | ||
|  |   RC_FORMAT_MINUTES, | ||
|  |   RC_FORMAT_SECONDS_AS_MINUTES | ||
|  | }; | ||
|  | 
 | ||
|  | int rc_parse_format(const char* format_str); | ||
|  | int rc_format_value(char* buffer, int size, int value, int format); | ||
|  | 
 | ||
|  | /*****************************************************************************\
 | ||
|  | | Rich Presence                                                               | | ||
|  | \*****************************************************************************/ | ||
|  | 
 | ||
|  | typedef struct rc_richpresence_lookup_item_t rc_richpresence_lookup_item_t; | ||
|  | 
 | ||
|  | struct rc_richpresence_lookup_item_t { | ||
|  |   unsigned first; | ||
|  |   unsigned last; | ||
|  |   rc_richpresence_lookup_item_t* left; | ||
|  |   rc_richpresence_lookup_item_t* right; | ||
|  |   const char* label; | ||
|  | }; | ||
|  | 
 | ||
|  | typedef struct rc_richpresence_lookup_t rc_richpresence_lookup_t; | ||
|  | 
 | ||
|  | struct rc_richpresence_lookup_t { | ||
|  |   rc_richpresence_lookup_item_t* root; | ||
|  |   rc_richpresence_lookup_t* next; | ||
|  |   const char* name; | ||
|  |   const char* default_label; | ||
|  |   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_t* lookup; | ||
|  |   rc_memref_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_t* memrefs; | ||
|  |   rc_value_t* variables; | ||
|  | } | ||
|  | 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); | ||
|  | void rc_update_richpresence(rc_richpresence_t* richpresence, rc_peek_t peek, void* peek_ud, lua_State* L); | ||
|  | int rc_get_richpresence_display_string(rc_richpresence_t* richpresence, char* buffer, unsigned buffersize, rc_peek_t peek, void* peek_ud, lua_State* L); | ||
|  | 
 | ||
|  | /*****************************************************************************\
 | ||
|  | | Runtime                                                                     | | ||
|  | \*****************************************************************************/ | ||
|  | 
 | ||
|  | typedef struct rc_runtime_trigger_t { | ||
|  |   unsigned id; | ||
|  |   rc_trigger_t* trigger; | ||
|  |   void* buffer; | ||
|  |   rc_memref_t* invalid_memref; | ||
|  |   unsigned char md5[16]; | ||
|  |   int serialized_size; | ||
|  |   char owns_memrefs; | ||
|  | } | ||
|  | rc_runtime_trigger_t; | ||
|  | 
 | ||
|  | typedef struct rc_runtime_lboard_t { | ||
|  |   unsigned id; | ||
|  |   int value; | ||
|  |   rc_lboard_t* lboard; | ||
|  |   void* buffer; | ||
|  |   rc_memref_t* invalid_memref; | ||
|  |   unsigned char md5[16]; | ||
|  |   char owns_memrefs; | ||
|  | } | ||
|  | rc_runtime_lboard_t; | ||
|  | 
 | ||
|  | typedef struct rc_runtime_richpresence_t { | ||
|  |   rc_richpresence_t* richpresence; | ||
|  |   void* buffer; | ||
|  |   struct rc_runtime_richpresence_t* previous; | ||
|  |   char owns_memrefs; | ||
|  | } | ||
|  | rc_runtime_richpresence_t; | ||
|  | 
 | ||
|  | typedef struct rc_runtime_t { | ||
|  |   rc_runtime_trigger_t* triggers; | ||
|  |   unsigned trigger_count; | ||
|  |   unsigned trigger_capacity; | ||
|  | 
 | ||
|  |   rc_runtime_lboard_t* lboards; | ||
|  |   unsigned lboard_count; | ||
|  |   unsigned lboard_capacity; | ||
|  | 
 | ||
|  |   rc_runtime_richpresence_t* richpresence; | ||
|  | 
 | ||
|  |   rc_memref_t* memrefs; | ||
|  |   rc_memref_t** next_memref; | ||
|  | 
 | ||
|  |   rc_value_t* variables; | ||
|  |   rc_value_t** next_variable; | ||
|  | } | ||
|  | rc_runtime_t; | ||
|  | 
 | ||
|  | void rc_runtime_init(rc_runtime_t* runtime); | ||
|  | void rc_runtime_destroy(rc_runtime_t* runtime); | ||
|  | 
 | ||
|  | int rc_runtime_activate_achievement(rc_runtime_t* runtime, unsigned id, const char* memaddr, lua_State* L, int funcs_idx); | ||
|  | void rc_runtime_deactivate_achievement(rc_runtime_t* runtime, unsigned id); | ||
|  | rc_trigger_t* rc_runtime_get_achievement(const rc_runtime_t* runtime, unsigned id); | ||
|  | 
 | ||
|  | int rc_runtime_activate_lboard(rc_runtime_t* runtime, unsigned id, const char* memaddr, lua_State* L, int funcs_idx); | ||
|  | void rc_runtime_deactivate_lboard(rc_runtime_t* runtime, unsigned id); | ||
|  | rc_lboard_t* rc_runtime_get_lboard(const rc_runtime_t* runtime, unsigned id); | ||
|  | 
 | ||
|  | int rc_runtime_activate_richpresence(rc_runtime_t* runtime, const char* script, lua_State* L, int funcs_idx); | ||
|  | int rc_runtime_get_richpresence(const rc_runtime_t* self, char* buffer, unsigned buffersize, rc_peek_t peek, void* peek_ud, lua_State* L); | ||
|  | 
 | ||
|  | enum { | ||
|  |   RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED, /* from WAITING, PAUSED, or PRIMED to ACTIVE */ | ||
|  |   RC_RUNTIME_EVENT_ACHIEVEMENT_PAUSED, | ||
|  |   RC_RUNTIME_EVENT_ACHIEVEMENT_RESET, | ||
|  |   RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED, | ||
|  |   RC_RUNTIME_EVENT_ACHIEVEMENT_PRIMED, | ||
|  |   RC_RUNTIME_EVENT_LBOARD_STARTED, | ||
|  |   RC_RUNTIME_EVENT_LBOARD_CANCELED, | ||
|  |   RC_RUNTIME_EVENT_LBOARD_UPDATED, | ||
|  |   RC_RUNTIME_EVENT_LBOARD_TRIGGERED, | ||
|  |   RC_RUNTIME_EVENT_ACHIEVEMENT_DISABLED, | ||
|  |   RC_RUNTIME_EVENT_LBOARD_DISABLED | ||
|  | }; | ||
|  | 
 | ||
|  | typedef struct rc_runtime_event_t { | ||
|  |   unsigned id; | ||
|  |   int value; | ||
|  |   char type; | ||
|  | } | ||
|  | rc_runtime_event_t; | ||
|  | 
 | ||
|  | typedef void (*rc_runtime_event_handler_t)(const rc_runtime_event_t* runtime_event); | ||
|  | 
 | ||
|  | void rc_runtime_do_frame(rc_runtime_t* runtime, rc_runtime_event_handler_t event_handler, rc_peek_t peek, void* ud, lua_State* L); | ||
|  | void rc_runtime_reset(rc_runtime_t* runtime); | ||
|  | void rc_runtime_invalidate_address(rc_runtime_t* runtime, unsigned address); | ||
|  | 
 | ||
|  | int rc_runtime_progress_size(const rc_runtime_t* runtime, lua_State* L); | ||
|  | int rc_runtime_serialize_progress(void* buffer, const rc_runtime_t* runtime, lua_State* L); | ||
|  | int rc_runtime_deserialize_progress(rc_runtime_t* runtime, const unsigned char* serialized, lua_State* L); | ||
|  | 
 | ||
|  | /*****************************************************************************\
 | ||
|  | | Memory mapping                                                              | | ||
|  | \*****************************************************************************/ | ||
|  | 
 | ||
|  | enum { | ||
|  |   RC_MEMORY_TYPE_SYSTEM_RAM,          /* normal system memory */ | ||
|  |   RC_MEMORY_TYPE_SAVE_RAM,            /* memory that persists between sessions */ | ||
|  |   RC_MEMORY_TYPE_VIDEO_RAM,           /* memory reserved for graphical processing */ | ||
|  |   RC_MEMORY_TYPE_READONLY,            /* memory that maps to read only data */ | ||
|  |   RC_MEMORY_TYPE_HARDWARE_CONTROLLER, /* memory for interacting with system components */ | ||
|  |   RC_MEMORY_TYPE_VIRTUAL_RAM,         /* secondary address space that maps to real memory in system RAM */ | ||
|  |   RC_MEMORY_TYPE_UNUSED               /* these addresses don't really exist */ | ||
|  | }; | ||
|  | 
 | ||
|  | typedef struct rc_memory_region_t { | ||
|  |   unsigned start_address;             /* first address of block as queried by RetroAchievements */ | ||
|  |   unsigned end_address;               /* last address of block as queried by RetroAchievements */ | ||
|  |   unsigned real_address;              /* real address for first address of block */ | ||
|  |   char type;                          /* RC_MEMORY_TYPE_ for block */ | ||
|  |   const char* description;            /* short description of block */ | ||
|  | } | ||
|  | rc_memory_region_t; | ||
|  | 
 | ||
|  | typedef struct rc_memory_regions_t { | ||
|  |   const rc_memory_region_t* region; | ||
|  |   unsigned num_regions; | ||
|  | } | ||
|  | rc_memory_regions_t; | ||
|  | 
 | ||
|  | const rc_memory_regions_t* rc_console_memory_regions(int console_id); | ||
|  | 
 | ||
|  | #ifdef __cplusplus
 | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #endif /* RCHEEVOS_H */
 |