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:
Andre Leiradella 2015-10-27 15:50:41 -02:00
parent 15adfdbe7d
commit 674752ca96
11 changed files with 1496 additions and 1046 deletions

View File

@ -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
View 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
View 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 */

View File

@ -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)

2177
cheevos.c

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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
View 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
View 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 */