Merge pull request #51 from ilag11111/cheatSupport

Add cheat support for Genesis/MegaDrive, CD, and 32X games
This commit is contained in:
Twinaphex 2017-03-23 20:18:00 +01:00 committed by GitHub
commit 6bf654d0e2
2 changed files with 94 additions and 4 deletions

View File

@ -142,7 +142,7 @@ static void hex_decode(const char *code, struct patch *result)
/* THIS is the function you call from the MegaDrive or whatever. This figures
* out whether it's a genie or hex code, depunctuates it, and calls the proper
* decoder. */
static void decode(const char* code, struct patch* result)
void decode(const char* code, struct patch* result)
{
int len = strlen(code), i, j;
char code_to_pass[16], *x;
@ -211,7 +211,8 @@ bad_code:
unsigned int PicoRead16(unsigned int a);
void PicoWrite16(unsigned int a, unsigned short d);
extern unsigned short m68k_read16(unsigned int a);
extern void m68k_write16(int a, unsigned short d);
void PicoPatchUnload(void)
{
@ -299,6 +300,8 @@ void PicoPatchPrepare(void)
PicoPatches[i].addr &= ~1;
if (PicoPatches[i].addr < Pico.romsize)
PicoPatches[i].data_old = *(unsigned short *)(Pico.rom + PicoPatches[i].addr);
else
PicoPatches[i].data_old = (unsigned short) m68k_read16(PicoPatches[i].addr);
if (strstr(PicoPatches[i].name, "AUTO"))
PicoPatches[i].active = 1;
}
@ -328,7 +331,15 @@ void PicoPatchApply(void)
}
else
{
/* TODO? */
if (PicoPatches[i].active)
m68k_write16(PicoPatches[i].addr,PicoPatches[i].data);
else {
// if current addr is not patched by older patch, write back original val
for (u = 0; u < i; u++)
if (PicoPatches[u].addr == addr) break;
if (u == i)
m68k_write16(PicoPatches[i].addr,PicoPatches[i].data_old);
}
}
}
}

View File

@ -53,6 +53,7 @@ int _newlib_vm_size_user = 1 << TARGET_SIZE_2;
#include <pico/pico_int.h>
#include <pico/state.h>
#include <pico/patch.h>
#include "../common/input_pico.h"
#include "../common/version.h"
#include "libretro.h"
@ -691,13 +692,90 @@ bool retro_unserialize(const void *data, size_t size)
return ret == 0;
}
/* cheats - TODO */
typedef struct patch
{
unsigned int addr;
unsigned short data;
} patch;
extern void decode(char *buff, patch *dest);
extern uint16_t m68k_read16(uint32_t a);
extern void m68k_write16(uint32_t a, uint16_t d);
void retro_cheat_reset(void)
{
int i=0;
unsigned int addr;
for (i = 0; i < PicoPatchCount; i++)
{
addr = PicoPatches[i].addr;
if (addr < Pico.romsize) {
if (PicoPatches[i].active)
*(unsigned short *)(Pico.rom + addr) = PicoPatches[i].data_old;
} else {
if (PicoPatches[i].active)
m68k_write16(PicoPatches[i].addr,PicoPatches[i].data_old);
}
}
PicoPatchUnload();
}
void retro_cheat_set(unsigned index, bool enabled, const char *code)
{
patch pt;
int array_len = PicoPatchCount;
char codeCopy[256];
char *buff;
bool multiline=0;
strcpy(codeCopy,code);
if (strstr(code,"+")){
multiline=1;
buff = strtok(codeCopy,"+");
} else {
buff=codeCopy;
}
while (buff != NULL)
{
decode(buff, &pt);
if (pt.addr == (uint32_t) -1 || pt.data == (uint16_t) -1)
{
log_cb(RETRO_LOG_ERROR,"CHEATS: Invalid code: %s\n",buff);
return;
}
/* code was good, add it */
if (array_len < PicoPatchCount + 1)
{
void *ptr;
array_len *= 2;
array_len++;
ptr = realloc(PicoPatches, array_len * sizeof(PicoPatches[0]));
if (ptr == NULL) {
log_cb(RETRO_LOG_ERROR,"CHEATS: Failed to allocate memory for: %s\n",buff);
return;
}
PicoPatches = ptr;
}
strcpy(PicoPatches[PicoPatchCount].code, buff);
PicoPatches[PicoPatchCount].active = enabled;
PicoPatches[PicoPatchCount].addr = pt.addr;
PicoPatches[PicoPatchCount].data = pt.data;
if (PicoPatches[PicoPatchCount].addr < Pico.romsize)
PicoPatches[PicoPatchCount].data_old = *(uint16_t *)(Pico.rom + PicoPatches[PicoPatchCount].addr);
else
PicoPatches[PicoPatchCount].data_old = (uint16_t) m68k_read16(PicoPatches[PicoPatchCount].addr);
PicoPatchCount++;
if (!multiline)
break;
buff = strtok(NULL,"+");
}
}
/* multidisk support */
@ -1270,6 +1348,7 @@ void retro_run(void)
if (input_state_cb(pad, RETRO_DEVICE_JOYPAD, 0, i))
PicoPad[pad] |= retro_pico_map[i];
PicoPatchApply();
PicoFrame();
video_cb((short *)vout_buf + vout_offset,