Patch System: Support Little Endian values for non-extended (#4255)

Allows users to use the leshort, leword, and ledouble datatypes inside their patches. Using these datatypes ensures that values in the memory view appear the same as the values in the patch.
This was made with easing patch development in mind as now developers can make patches without having to reverse endianness. This is especially useful when using programs like ghidra who display an instructions bytes in little endian.
This commit is contained in:
Tupelov 2021-02-26 19:38:12 -08:00 committed by GitHub
parent 9e3fb9f3ce
commit e42d506a64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 2 deletions

View File

@ -61,6 +61,9 @@ static const PatchTextTable dataType[] =
{ 3, L"word", NULL },
{ 4, L"double", NULL },
{ 5, L"extended", NULL },
{ 6, L"leshort", NULL},
{ 7, L"leword", NULL},
{ 8, L"ledouble", NULL},
{ 0, wxEmptyString, NULL }
};

View File

@ -51,7 +51,10 @@ enum patch_data_type {
SHORT_T,
WORD_T,
DOUBLE_T,
EXTENDED_T
EXTENDED_T,
SHORT_LE_T,
WORD_LE_T,
DOUBLE_LE_T
};
// "place" is the first number at a pnach line (patch=<place>,...), e.g.:
@ -128,3 +131,8 @@ extern void PatchesVerboseReset();
// regardless, they don't seem to have an implementation anywhere.
// extern int AddPatch(int Mode, int Place, int Address, int Size, u64 data);
// extern void ResetPatch(void);
// Swaps endianess of InputNum
// ex. 01020304 -> 04030201
// BitLength is length of InputNum in bits, ex. double,64 word,32 short,16
extern u64 SwapEndian(u64 InputNum, u8 BitLength);

View File

@ -387,6 +387,9 @@ void handle_extended_t(IniPatch *p)
// Patch.cpp itself declares this prototype, so make sure to keep in sync.
void _ApplyPatch(IniPatch *p)
{
u64 mem = 0;
u64 ledata = 0;
if (p->enabled == 0) return;
switch (p->cpu)
@ -410,7 +413,6 @@ void _ApplyPatch(IniPatch *p)
break;
case DOUBLE_T:
u64 mem;
memRead64(p->addr, &mem);
if (mem != p->data)
memWrite64(p->addr, &p->data);
@ -420,6 +422,25 @@ void _ApplyPatch(IniPatch *p)
handle_extended_t(p);
break;
case SHORT_LE_T:
ledata = SwapEndian(p->data, 16);
if (memRead16(p->addr) != (u16)ledata)
memWrite16(p->addr, (u16)ledata);
break;
case WORD_LE_T:
ledata = SwapEndian(p->data, 32);
if (memRead32(p->addr) != (u32)ledata)
memWrite32(p->addr, (u32)ledata);
break;
case DOUBLE_LE_T:
ledata = SwapEndian(p->data, 64);
memRead64(p->addr, &mem);
if (mem != ledata)
memWrite64(p->addr, ledata);
break;
default:
break;
}
@ -449,3 +470,18 @@ void _ApplyPatch(IniPatch *p)
break;
}
}
u64 SwapEndian(u64 InputNum, u8 BitLength)
{
if (BitLength == 64) // DOUBLE_LE_T
{
InputNum = (InputNum & 0x00000000FFFFFFFF) << 32 | (InputNum & 0xFFFFFFFF00000000) >> 32; //Swaps 4 bytes
}
if ((BitLength == 32)||(BitLength==64)) // WORD_LE_T
{
InputNum = (InputNum & 0x0000FFFF0000FFFF) << 16 | (InputNum & 0xFFFF0000FFFF0000) >> 16; // Swaps 2 bytes
}
InputNum = (InputNum & 0x00FF00FF00FF00FF) << 8 | (InputNum & 0xFF00FF00FF00FF00) >> 8; // Swaps 1 byte
return InputNum;
}