mirror of
https://github.com/CTCaer/RetroArch.git
synced 2024-12-05 01:16:38 +00:00
sumbit achievements asynchronously to the server; download list of unlocked achievements to prevent earning the same achievement more than once; disabled achievements if the game was started with cheats enabled or after they were enabled during game play; fixed code style
This commit is contained in:
parent
15adfdbe7d
commit
674752ca96
@ -856,7 +856,7 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
ifeq ($(HAVE_CHEEVOS), 1)
|
||||
ifeq ($(HAVE_THREADS), 1)
|
||||
DEFINES += -DHAVE_CHEEVOS
|
||||
OBJ += cheevos.o libretro-common/utils/md5.o
|
||||
OBJ += cheevos.o semaphore.o async_job.o libretro-common/utils/md5.o
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
137
async_job.c
Normal file
137
async_job.c
Normal file
@ -0,0 +1,137 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015 - Andre Leiradella
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rthreads/rthreads.h>
|
||||
#include <semaphore.h>
|
||||
#include <async_job.h>
|
||||
|
||||
typedef struct async_job_node async_job_node_t;
|
||||
|
||||
struct async_job_node
|
||||
{
|
||||
async_task_t task;
|
||||
void *payload;
|
||||
async_job_node_t *next;
|
||||
};
|
||||
|
||||
struct async_job
|
||||
{
|
||||
async_job_node_t *first;
|
||||
async_job_node_t *last;
|
||||
volatile int finish;
|
||||
slock_t *lock;
|
||||
ssem_t *sem;
|
||||
sthread_t* thread;
|
||||
};
|
||||
|
||||
static void processor(void *userdata)
|
||||
{
|
||||
async_job_t *ajob = (async_job_t*)userdata;
|
||||
async_job_node_t *node;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ssem_wait(ajob->sem);
|
||||
|
||||
if (ajob->finish)
|
||||
return;
|
||||
|
||||
slock_lock(ajob->lock);
|
||||
|
||||
node = ajob->first;
|
||||
ajob->first = node->next;
|
||||
|
||||
slock_unlock(ajob->lock);
|
||||
|
||||
node->task(node->payload);
|
||||
free((void*)node);
|
||||
}
|
||||
}
|
||||
|
||||
async_job_t *async_job_new(void)
|
||||
{
|
||||
async_job_t *ajob = (async_job_t*)malloc(sizeof(*ajob));
|
||||
|
||||
if (ajob)
|
||||
{
|
||||
ajob->first = NULL;
|
||||
ajob->last = NULL;
|
||||
ajob->finish = 0;
|
||||
ajob->lock = slock_new();
|
||||
|
||||
if (ajob->lock)
|
||||
{
|
||||
ajob->sem = ssem_new(0);
|
||||
|
||||
if (ajob->sem)
|
||||
{
|
||||
ajob->thread = sthread_create(processor, (void*)ajob);
|
||||
|
||||
if (ajob->thread)
|
||||
return ajob;
|
||||
|
||||
ssem_free(ajob->sem);
|
||||
}
|
||||
|
||||
slock_free(ajob->lock);
|
||||
}
|
||||
|
||||
free((void*)ajob);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void async_job_free(async_job_t *ajob)
|
||||
{
|
||||
ajob->finish = 1;
|
||||
ssem_signal(ajob->sem);
|
||||
sthread_join(ajob->thread);
|
||||
ssem_free(ajob->sem);
|
||||
free((void*)ajob);
|
||||
}
|
||||
|
||||
int async_job_add(async_job_t *ajob, async_task_t task, void *payload)
|
||||
{
|
||||
async_job_node_t *node = (async_job_node_t*)malloc(sizeof(*node));
|
||||
|
||||
if (node)
|
||||
{
|
||||
node->task = task;
|
||||
node->payload = payload;
|
||||
node->next = NULL;
|
||||
|
||||
slock_lock(ajob->lock);
|
||||
|
||||
if (ajob->first)
|
||||
{
|
||||
ajob->last->next = node;
|
||||
ajob->last = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
ajob->first = ajob->last = node;
|
||||
}
|
||||
|
||||
slock_unlock(ajob->lock);
|
||||
ssem_signal(ajob->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
28
async_job.h
Normal file
28
async_job.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015 - Andre Leiradella
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_ASYNC_JOB_H
|
||||
#define __RARCH_ASYNC_JOB_H
|
||||
|
||||
typedef struct async_job async_job_t;
|
||||
typedef void (*async_task_t)(void *payload);
|
||||
|
||||
async_job_t *async_job_new(void);
|
||||
|
||||
void async_job_free(async_job_t *ajob);
|
||||
|
||||
int async_job_add(async_job_t *ajob, async_task_t task, void *payload);
|
||||
|
||||
#endif /* __RARCH_ASYNC_JOB_H */
|
11
cheats.c
11
cheats.c
@ -23,7 +23,7 @@
|
||||
#include <compat/strl.h>
|
||||
#include <compat/posix_string.h>
|
||||
|
||||
#include "cheats.h"
|
||||
#include "cheevos.h"
|
||||
#include "general.h"
|
||||
#include "runloop.h"
|
||||
#include "dynamic.h"
|
||||
@ -32,6 +32,10 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
#include "cheats.h"
|
||||
#endif
|
||||
|
||||
struct item_cheat
|
||||
{
|
||||
char *desc;
|
||||
@ -75,6 +79,11 @@ void cheat_manager_apply_cheats(cheat_manager_t *handle)
|
||||
if (handle->cheats[i].state)
|
||||
core.retro_cheat_set(idx++, true, handle->cheats[i].code);
|
||||
}
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
cheevos_globals.cheats_are_enabled = idx != 0;
|
||||
cheevos_globals.cheats_were_enabled |= cheevos_globals.cheats_are_enabled;
|
||||
#endif
|
||||
}
|
||||
|
||||
void cheat_manager_set_code(cheat_manager_t *handle, unsigned i, const char *str)
|
||||
|
14
cheevos.h
14
cheevos.h
@ -16,12 +16,18 @@
|
||||
#ifndef __RARCH_CHEEVOS_H
|
||||
#define __RARCH_CHEEVOS_H
|
||||
|
||||
int cheevos_load( const char *json );
|
||||
typedef struct
|
||||
{
|
||||
int cheats_are_enabled;
|
||||
int cheats_were_enabled;
|
||||
} cheevos_globals_t;
|
||||
|
||||
void cheevos_test( void );
|
||||
extern cheevos_globals_t cheevos_globals;
|
||||
|
||||
void cheevos_unload( void );
|
||||
int cheevos_load(const void *data, size_t size);
|
||||
|
||||
int cheevos_get_by_content( const char **json, const void *data, size_t size );
|
||||
void cheevos_test(void);
|
||||
|
||||
void cheevos_unload(void);
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_H */
|
||||
|
@ -1109,6 +1109,10 @@ bool event_command(enum event_command cmd)
|
||||
case EVENT_CMD_RESET:
|
||||
RARCH_LOG("%s.\n", msg_hash_to_str(MSG_RESET));
|
||||
rarch_main_msg_queue_push_new(MSG_RESET, 1, 120, true);
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
cheevos_globals.cheats_were_enabled = cheevos_globals.cheats_are_enabled;
|
||||
#endif
|
||||
core.retro_reset();
|
||||
|
||||
/* bSNES since v073r01 resets controllers to JOYPAD
|
||||
|
13
content.c
13
content.c
@ -44,7 +44,10 @@
|
||||
#include "movie.h"
|
||||
#include "patch.h"
|
||||
#include "system.h"
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
#include "cheevos.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* read_content_file:
|
||||
@ -517,14 +520,8 @@ static bool load_content(const struct retro_subsystem_info *special,
|
||||
|
||||
if (*content->elems[0].data)
|
||||
{
|
||||
|
||||
const char *json = NULL;
|
||||
|
||||
if ( cheevos_get_by_content(&json, info->data, info->size) == 0 )
|
||||
{
|
||||
cheevos_load(json);
|
||||
free((void*)json);
|
||||
}
|
||||
cheevos_globals.cheats_were_enabled = cheevos_globals.cheats_are_enabled;
|
||||
cheevos_load(info->data, info->size);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -70,16 +70,10 @@ CONFIG FILE
|
||||
#include "../libretro-common/file/config_file_userdata.c"
|
||||
#include "../core_options.c"
|
||||
|
||||
/*============================================================
|
||||
CHEATS
|
||||
============================================================ */
|
||||
#include "../cheats.c"
|
||||
#include "../libretro-common/hash/rhash.c"
|
||||
|
||||
/*============================================================
|
||||
ACHIEVEMENTS
|
||||
============================================================ */
|
||||
#if defined(HAVE_CHEEVOS)
|
||||
#if defined(HAVE_CHEEVOS) && defined(HAVE_THREADS)
|
||||
#if !defined(HAVE_NETPLAY)
|
||||
#include "../libretro-common/net/net_http.c"
|
||||
#endif
|
||||
@ -87,9 +81,17 @@ ACHIEVEMENTS
|
||||
#include "../libretro-common/formats/json/jsonsax.c"
|
||||
#include "../libretro-common/utils/md5.c"
|
||||
#include "../net_http_special.c"
|
||||
#include "../semaphore.c"
|
||||
#include "../async_job.c"
|
||||
#include "../cheevos.c"
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
CHEATS
|
||||
============================================================ */
|
||||
#include "../cheats.c"
|
||||
#include "../libretro-common/hash/rhash.c"
|
||||
|
||||
/*============================================================
|
||||
UI COMMON CONTEXT
|
||||
============================================================ */
|
||||
|
103
semaphore.c
Normal file
103
semaphore.c
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
Copyright 2005 Allen B. Downey
|
||||
|
||||
This file contains an example program from The Little Book of
|
||||
Semaphores, available from Green Tea Press, greenteapress.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc., 51 Franklin St,
|
||||
Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* Code taken from http://greenteapress.com/semaphores/semaphore.c
|
||||
* and changed to use libretro-common's mutexes and conditions.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rthreads/rthreads.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
struct ssem
|
||||
{
|
||||
int value, wakeups;
|
||||
slock_t *mutex;
|
||||
scond_t *cond;
|
||||
};
|
||||
|
||||
ssem_t *ssem_new(int value)
|
||||
{
|
||||
ssem_t *semaphore = (ssem_t*)malloc(sizeof(*semaphore));
|
||||
|
||||
if (semaphore)
|
||||
{
|
||||
semaphore->value = value;
|
||||
semaphore->wakeups = 0;
|
||||
semaphore->mutex = slock_new();
|
||||
|
||||
if (semaphore->mutex)
|
||||
{
|
||||
semaphore->cond = scond_new();
|
||||
|
||||
if (semaphore->cond)
|
||||
return semaphore;
|
||||
|
||||
slock_free(semaphore->mutex);
|
||||
}
|
||||
|
||||
free((void*)semaphore);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ssem_free(ssem_t *semaphore)
|
||||
{
|
||||
scond_free(semaphore->cond);
|
||||
slock_free(semaphore->mutex);
|
||||
free((void*)semaphore);
|
||||
}
|
||||
|
||||
void ssem_wait(ssem_t *semaphore)
|
||||
{
|
||||
slock_lock(semaphore->mutex);
|
||||
semaphore->value--;
|
||||
|
||||
if (semaphore->value < 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
scond_wait(semaphore->cond, semaphore->mutex);
|
||||
}
|
||||
while (semaphore->wakeups < 1);
|
||||
|
||||
semaphore->wakeups--;
|
||||
}
|
||||
|
||||
slock_unlock(semaphore->mutex);
|
||||
}
|
||||
|
||||
void ssem_signal(ssem_t *semaphore)
|
||||
{
|
||||
slock_lock(semaphore->mutex);
|
||||
semaphore->value++;
|
||||
|
||||
if (semaphore->value <= 0)
|
||||
{
|
||||
semaphore->wakeups++;
|
||||
scond_signal(semaphore->cond);
|
||||
}
|
||||
|
||||
slock_unlock(semaphore->mutex);
|
||||
}
|
37
semaphore.h
Normal file
37
semaphore.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015 - Andre Leiradella
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_SEMAPHORE_H
|
||||
#define __RARCH_SEMAPHORE_H
|
||||
|
||||
typedef struct ssem ssem_t;
|
||||
|
||||
/**
|
||||
* ssem_create:
|
||||
* @value : initial value for the semaphore
|
||||
*
|
||||
* Create a new semaphore.
|
||||
*
|
||||
* Returns: pointer to new semaphore if successful, otherwise NULL.
|
||||
*/
|
||||
ssem_t *ssem_new(int value);
|
||||
|
||||
void ssem_free(ssem_t *semaphore);
|
||||
|
||||
void ssem_wait(ssem_t *semaphore);
|
||||
|
||||
void ssem_signal(ssem_t *semaphore);
|
||||
|
||||
#endif /* __RARCH_SEMAPHORE_H */
|
Loading…
Reference in New Issue
Block a user