daedalus/Source/OSHLE/patch.h
2024-08-05 21:15:57 +10:00

195 lines
5 KiB
C

/*
Copyright (C) 2001 StrmnNrmn
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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef OSHLE_PATCH_H_
#define OSHLE_PATCH_H_
#include "Debug/Registers.h" // For SRHACK_???? etc
#include "Core/CPU.h" // Breakpoint stuff
#include "Ultra/ultra_R4300.h"
//#define DUMPOSFUNCTIONS
// Returns return type to determine what kind of post-processing should occur
using PatchFunction = u32 (*) ();
#define VAR_ADDRESS(name) (g_##name##_v.Location)
#define VAR_FOUND(name) (g_##name##_v.Found)
enum PATCH_CROSSREF_TYPE
{
PX_JUMP,
PX_VARIABLE_HI,
PX_VARIABLE_LO
};
struct _PatchSymbol;
typedef struct
{
u32 Offset; // Opcode offset
PATCH_CROSSREF_TYPE Type; // Type - J/JAL/LUI/ORI
struct _PatchSymbol * Symbol; // Only one of these is valid
struct _PatchVariable * Variable;
} PatchCrossRef;
#define PATCH_PARTIAL_CRC_LEN 4
typedef struct
{
u32 NumOps;
PatchCrossRef * CrossRefs;
PatchFunction Function;
u32 FirstOp; // First op in signature (used for rapid scanning)
u32 PartialCRC; // Crc after 4 ops (ignoring symbol bits)
u32 CRC; // Crc for entire buffer (ignoring symbol bits)
} PatchSignature;
typedef struct _PatchSymbol
{
bool Found; // Has this symbol been found?
u32 Location; // What is the address of the symbol?
const char * Name; // Symbol name
PatchSignature * Signatures; // Crossrefs for this code (Function symbols only)
PatchFunction Function; // The installed patch Emulated function call (Function symbols only)
} PatchSymbol;
typedef struct _PatchVariable
{
bool Found; // Has this symbol been found?
u32 Location; // What is the address of the symbol?
const char * Name; // Symbol name
// For now have these as separate fields. We probably want to
// put them into a union
bool FoundHi;
bool FoundLo;
u16 HiWord;
u16 LoWord;
} PatchVariable;
///////////////////////////////////////////////////////////////
#define BEGIN_PATCH_XREFS(label) \
static PatchCrossRef g_##label##_x[] = {
#define PATCH_XREF_FUNCTION(offset, symbol) \
{ offset, PX_JUMP, &g_##symbol##_s, NULL },
#define PATCH_XREF_VAR(offsethi, offsetlo, symbol) \
{ offsethi, PX_VARIABLE_HI, NULL, &g_##symbol##_v }, \
{ offsetlo, PX_VARIABLE_LO, NULL, &g_##symbol##_v },
#define PATCH_XREF_VAR_LO(offset, symbol) \
{ offset, PX_VARIABLE_LO, NULL, &g_##symbol##_v },
#define PATCH_XREF_VAR_HI(offset, symbol) \
{ offset, PX_VARIABLE_HI, NULL, &g_##symbol##_v },
#define END_PATCH_XREFS() \
{ static_cast<u32>(~0), PX_JUMP, NULL, NULL } \
};
/////////////////////////////////////////////////////////////////
#define BEGIN_PATCH_SIGNATURE_LIST(name) \
static PatchSignature g_##name##_sig[] = {
#define PATCH_SIGNATURE_LIST_ENTRY(label, numops, firstop, partial, crc) \
{ numops, g_##label##_x, Patch_##label, firstop, partial, crc },
#define END_PATCH_SIGNATURE_LIST() \
{ 0, NULL, NULL, 0, 0, 0 } \
};
///////////////////////////////////////////////////////////////
#define PATCH_SYMBOL_FUNCTION(name) \
PatchSymbol g_##name##_s = { false, 0, #name, g_##name##_sig, NULL};
#define PATCH_SYMBOL_VARIABLE(name) \
PatchVariable g_##name##_v = { false, 0, #name, false, 0, false, 0};
#define BEGIN_PATCH_SYMBOL_TABLE(name) \
PatchSymbol * name[] = {
#define PATCH_FUNCTION_ENTRY(name) \
&g_##name##_s,
#define END_PATCH_SYMBOL_TABLE() \
NULL};
#define PATCH_SYMBOL_FUNCTION_ENTRY(name) g_##name##_s
#define BEGIN_PATCH_VARIABLE_TABLE(name) \
PatchVariable * name[] = {
#define PATCH_VARIABLE_ENTRY(name) \
&g_##name##_v,
#define END_PATCH_VARIABLE_TABLE() \
NULL};
#define CALL_PATCHED_FUNCTION(name) g_##name##_s.Function()
#ifdef DAEDALUS_ENABLE_OS_HOOKS
extern PatchSymbol * g_PatchSymbols[];
extern PatchVariable * g_PatchVariables[];
#endif
inline OpCode GetCorrectOp( OpCode op_code )
{
#ifdef DAEDALUS_BREAKPOINTS_ENABLED
if (op_code.op == OP_DBG_BKPT)
{
u32 bp_index = op_code.bp_index;
if (bp_index < g_BreakPoints.size())
{
op_code = g_BreakPoints[bp_index].mOriginalOp;
}
}
#endif
return op_code;
}
extern u32 gNumOfOSFunctions;
void Patch_Reset();
void Patch_ApplyPatches();
void Patch_PatchAll();
#ifndef DAEDALUS_SILENT
const char * Patch_GetJumpAddressName(u32 jump);
u32 Patch_GetSymbolAddress(const char * name);
#endif
#ifdef DUMPOSFUNCTIONS
void Patch_DumpOsThreadInfo();
void Patch_DumpOsQueueInfo();
void Patch_DumpOsEventInfo();
#endif
#endif // OSHLE_PATCH_H_