Merge pull request #75 from ilag11111/cheatSupport

Add support for multiline cheats and Master System cheats
This commit is contained in:
Twinaphex 2017-03-25 23:39:36 +01:00 committed by GitHub
commit 71c0eb3091

View File

@ -1190,114 +1190,57 @@ static uint32_t decode_cheat(char *string, int index)
uint32_t address = 0;
uint16_t data = 0;
uint8_t ref = 0;
/* 16-bit Game Genie code (ABCD-EFGH) */
if ((strlen(string) >= 9) && (string[4] == '-'))
{
/* 16-bit system only */
if ((system_hw & SYSTEM_PBC) != SYSTEM_MD)
if ((system_hw & SYSTEM_PBC) == SYSTEM_MD){
//If system is Genesis-based
//Game-Genie
if ((strlen(string) >= 9) && (string[4] == '-'))
{
return 0;
}
for (i = 0; i < 8; i++)
{
if (i == 4) string++;
p = strchr (ggvalidchars, *string++);
if (p == NULL) return 0;
n = p - ggvalidchars;
switch (i)
for (i = 0; i < 8; i++)
{
case 0:
data |= n << 3;
break;
case 1:
data |= n >> 2;
address |= (n & 3) << 14;
break;
case 2:
address |= n << 9;
break;
case 3:
address |= (n & 0xF) << 20 | (n >> 4) << 8;
break;
case 4:
data |= (n & 1) << 12;
address |= (n >> 1) << 16;
break;
case 5:
data |= (n & 1) << 15 | (n >> 1) << 8;
break;
case 6:
data |= (n >> 3) << 13;
address |= (n & 7) << 5;
break;
case 7:
address |= n;
break;
if (i == 4) string++;
p = strchr (ggvalidchars, *string++);
if (p == NULL) return 0;
n = p - ggvalidchars;
switch (i)
{
case 0:
data |= n << 3;
break;
case 1:
data |= n >> 2;
address |= (n & 3) << 14;
break;
case 2:
address |= n << 9;
break;
case 3:
address |= (n & 0xF) << 20 | (n >> 4) << 8;
break;
case 4:
data |= (n & 1) << 12;
address |= (n >> 1) << 16;
break;
case 5:
data |= (n & 1) << 15 | (n >> 1) << 8;
break;
case 6:
data |= (n >> 3) << 13;
address |= (n & 7) << 5;
break;
case 7:
address |= n;
break;
}
}
/* code length */
len = 9;
}
/* code length */
len = 9;
}
/* 8-bit Game Genie code (DDA-AAA-XXX) */
else if ((strlen(string) >= 11) && (string[3] == '-') && (string[7] == '-'))
{
/* 8-bit system only */
if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
//Patch and PAR
else if ((strlen(string) >=9) && (string[6] == ':'))
{
return 0;
}
/* decode 8-bit data */
for (i=0; i<2; i++)
{
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
data |= (n << ((1 - i) * 4));
}
/* decode 16-bit address (low 12-bits) */
for (i=0; i<3; i++)
{
if (i==1) string++; /* skip separator */
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
address |= (n << ((2 - i) * 4));
}
/* decode 16-bit address (high 4-bits) */
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
n ^= 0xF; /* bits inversion */
address |= (n << 12);
/* RAM address are also supported */
if (address >= 0xC000)
{
/* convert to 24-bit Work RAM address */
address = 0xFF0000 | (address & 0x1FFF);
}
/* decode reference 8-bit data */
for (i=0; i<2; i++)
{
string++; /* skip separator and 2nd digit */
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
ref |= (n << ((1 - i) * 4));
}
ref = (ref >> 2) | ((ref & 0x03) << 6); /* 2-bit right rotation */
ref ^= 0xBA; /* XOR */
/* update old data value */
cheatlist[index].old = ref;
/* code length */
len = 11;
}
/* Action Replay code */
else if (string[6] == ':')
{
if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
{
/* 16-bit code (AAAAAA:DDDD) */
if (strlen(string) < 11) return 0;
/* decode 24-bit address */
for (i=0; i<6; i++)
{
@ -1311,19 +1254,93 @@ static uint32_t decode_cheat(char *string, int index)
for (i=0; i<4; i++)
{
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
if (p == NULL) break;
n = (p - arvalidchars) & 0xF;
data |= (n << ((3 - i) * 4));
}
/* code length */
len = 11;
}
else
} else {
//If System is Master-based
//Game Genie
if ((strlen(string) >=11) && (string[3] == '-') && (string[7] == '-'))
{
/* 8-bit code (xxAAAA:DD) */
if (strlen(string) < 9) return 0;
/* decode 16-bit address */
/* decode 8-bit data */
for (i=0; i<2; i++)
{
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
data |= (n << ((1 - i) * 4));
}
/* decode 16-bit address (low 12-bits) */
for (i=0; i<3; i++)
{
if (i==1) string++; /* skip separator */
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
address |= (n << ((2 - i) * 4));
}
/* decode 16-bit address (high 4-bits) */
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
n ^= 0xF; /* bits inversion */
address |= (n << 12);
/* RAM address are also supported */
if (address >= 0xC000)
{
/* convert to 24-bit Work RAM address */
address = 0xFF0000 | (address & 0x1FFF);
}
/* decode reference 8-bit data */
for (i=0; i<2; i++)
{
string++; /* skip separator and 2nd digit */
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
ref |= (n << ((1 - i) * 4));
}
ref = (ref >> 2) | ((ref & 0x03) << 6); /* 2-bit right rotation */
ref ^= 0xBA; /* XOR */
/* update old data value */
cheatlist[index].old = ref;
/* code length */
len = 11;
}
//Action Replay
else if ((strlen(string) >=9) && (string[4] == '-')){
string+=2;
/* decode 16-bit address */
for (i=0; i<4; i++)
{
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
address |= (n << ((3 - i) * 4));
if (i==1) string++;
}
/* decode 8-bit data */
for (i=0; i<2; i++)
{
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
data |= (n << ((1 - i) * 4));
}
/* code length */
len = 9;
}
//Fusion RAM
else if ((strlen(string) >=7) && (string[4] == ':'))
{
/* decode 16-bit address */
for (i=0; i<4; i++)
{
p = strchr (arvalidchars, *string++);
@ -1331,10 +1348,6 @@ static uint32_t decode_cheat(char *string, int index)
n = (p - arvalidchars) & 0xF;
address |= (n << ((3 - i) * 4));
}
/* ROM addresses are not supported */
if (address < 0xC000) return 0;
/* convert to 24-bit Work RAM address */
address = 0xFF0000 | (address & 0x1FFF);
/* decode 8-bit data */
string++;
for (i=0; i<2; i++)
@ -1345,6 +1358,40 @@ static uint32_t decode_cheat(char *string, int index)
data |= (n << ((1 - i) * 4));
}
/* code length */
len = 7;
}
//Fusion ROM
else if ((strlen(string) >=9) && (string[6] == ':'))
{
/* decode reference 8-bit data */
for (i=0; i<2; i++)
{
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
ref |= (n << ((1 - i) * 4));
}
/* decode 16-bit address */
for (i=0; i<4; i++)
{
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
address |= (n << ((3 - i) * 4));
}
/* decode 8-bit data */
string++;
for (i=0; i<2; i++)
{
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
data |= (n << ((1 - i) * 4));
}
/* update old data value */
cheatlist[index].old = ref;
/* code length */
len = 9;
}
}
@ -1892,32 +1939,46 @@ void retro_cheat_reset(void)
void retro_cheat_set(unsigned index, bool enabled, const char *code)
{
char codeCopy[256];
char *buff;
/* Avoid crashing when giving empty input */
if (code=='\0') return;
/* clear existing ROM patches */
clear_cheats();
/* interpret code and check if this is a valid cheat code */
if (decode_cheat((char *)code, maxcheats))
{
int i;
/* Detect and split multiline cheats */
strcpy(codeCopy,code);
buff = strtok(codeCopy,"+");
/* check if cheat code already exists */
for (i=0; i<maxcheats; i++)
while (buff != NULL)
{
/* interpret code and check if this is a valid cheat code */
if (decode_cheat((char *)buff, maxcheats))
{
if ((cheatlist[i].address == cheatlist[maxcheats].address)
&& (cheatlist[i].data == cheatlist[maxcheats].data))
break;
}
int i;
/* cheat can be enabled or disabled */
cheatlist[i].enable = enabled;
/* check if cheat code already exists */
for (i=0; i<maxcheats; i++)
{
if ((cheatlist[i].address == cheatlist[maxcheats].address)
&& (cheatlist[i].data == cheatlist[maxcheats].data))
break;
}
/* if new cheat code, check current cheat count */
if ((i == maxcheats) && (i < MAX_CHEATS))
{
/* increment cheat count */
maxcheats++;
/* cheat can be enabled or disabled */
cheatlist[i].enable = enabled;
/* if new cheat code, check current cheat count */
if ((i == maxcheats) && (i < MAX_CHEATS))
{
/* increment cheat count */
maxcheats++;
}
}
}
buff = strtok(NULL,"+");
}
/* apply ROM patches */
apply_cheats();