BizHawk/mednafen/src/debug.cpp

238 lines
5.7 KiB
C++

/* Mednafen - Multi-system Emulator
*
* 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
*/
/* Support functions for the emulated system code-side of the debugger. */
#include "mednafen.h"
#ifdef WANT_DEBUGGER
static std::vector<AddressSpaceType> AddressSpaces;
static std::vector<RegGroupType*> RegGroups;
// Currently only called on emulator startup, not game load...
void MDFNDBG_Init(void)
{
AddressSpaces.clear();
RegGroups.clear();
}
void MDFNDBG_PostGameLoad(void)
{
if(MDFNGameInfo->Debugger)
{
MDFNGameInfo->Debugger->AddressSpaces = &AddressSpaces;
MDFNGameInfo->Debugger->RegGroups = &RegGroups;
}
}
// Called on game close.
void MDFNDBG_Kill(void)
{
for(unsigned int x = 0; x < AddressSpaces.size(); x++)
{
if(AddressSpaces[x].name)
free(AddressSpaces[x].name);
if(AddressSpaces[x].long_name)
free(AddressSpaces[x].long_name);
}
AddressSpaces.clear();
RegGroups.clear();
}
int ASpace_Add(void (*gasb)(const char *name, uint32 Address, uint32 Length, uint8 *Buffer),
void (*pasb)(const char *name, uint32 Address, uint32 Length, uint32 Granularity, bool hl, const uint8 *Buffer), const char *name, const char *long_name,
uint32 TotalBits, uint32 NP2Size, bool IsSegmented, uint32 SegmentBits, uint32 OffsetBits, uint32 BitsOverlapped)
{
AddressSpaceType newt;
memset(&newt, 0, sizeof(newt));
newt.GetAddressSpaceBytes = gasb;
newt.PutAddressSpaceBytes = pasb;
newt.name = strdup(name);
newt.long_name = strdup(long_name);
newt.TotalBits = TotalBits;
newt.NP2Size = NP2Size;
newt.IsSegmented = IsSegmented;
newt.SegmentBits = SegmentBits;
newt.OffsetBits = OffsetBits;
newt.BitsOverlapped = BitsOverlapped;
AddressSpaces.push_back(newt);
return(AddressSpaces.size() - 1);
}
int ASpace_Add(const AddressSpaceType &newt)
{
AddressSpaces.push_back(newt);
return(AddressSpaces.size() - 1);
}
// Returns number of new bytes allocated.
static INLINE uint64 IncUsageMap(uint64 *****UsageMap, const uint32 address)
{
uint64 ret = 0;
if(!(*UsageMap))
{
(*UsageMap) = (uint64 ****)MDFN_calloc(sizeof(uint64 ***), 256, "Usage map");
ret += sizeof(uint64 ***) * 256;
}
if(!(*UsageMap)[address >> 24])
{
(*UsageMap)[address >> 24] = (uint64 ***)MDFN_calloc(sizeof(uint64 **), 256, "Usage map");
ret += sizeof(uint64 **) * 256;
}
if(!(*UsageMap)[address >> 24][(address >> 16) & 0xFF])
{
(*UsageMap)[address >> 24][(address >> 16) & 0xFF] = (uint64 **)MDFN_calloc(sizeof(uint64 *), 256, "Usage map");
ret += sizeof(uint64 *) * 256;
}
if(!(*UsageMap)[address >> 24][(address >> 16) & 0xFF][(address >> 8) & 0xFF])
{
(*UsageMap)[address >> 24][(address >> 16) & 0xFF][(address >> 8) & 0xFF] = (uint64 *)MDFN_calloc(sizeof(uint64), 256, "Usage map");
ret += sizeof(uint64) * 256;
}
(*UsageMap)[address >> 24][(address >> 16) & 0xFF][(address >> 8) & 0xFF][address & 0xFF]++;
return(ret);
}
bool ASpace_Read(const int id, const uint32 address, const unsigned int size, const bool pre_bpoint)
{
AddressSpaceType *as;
assert(id > 0 && (const unsigned int)id < AddressSpaces.size());
as = &AddressSpaces[id];
if(pre_bpoint)
return(FALSE);
else
{
as->UsageReadMemUsed += IncUsageMap(&as->UsageMapRead, address);
}
return(FALSE);
}
bool ASpace_Write(const int id, const uint32 address, const uint32 value, const unsigned int size, const bool pre_bpoint)
{
AddressSpaceType *as;
assert(id > 0 && (const unsigned int)id < AddressSpaces.size());
as = &AddressSpaces[id];
if(pre_bpoint)
return(FALSE);
else
{
as->UsageWriteMemUsed += IncUsageMap(&as->UsageMapWrite, address);
return(FALSE);
}
}
static INLINE void ClearUsageMap(uint64 *****UsageMap)
{
// Maybe we should use an alloced memory vector to speed this up...
if((*UsageMap))
{
for(int a = 0; a < 256; a++)
{
if((*UsageMap)[a])
{
for(int b = 0; b < 256; b++)
{
if((*UsageMap)[a][b])
{
for(int c = 0; c < 256; c++)
{
if((*UsageMap)[a][b][c])
{
MDFN_free((*UsageMap)[a][b][c]);
(*UsageMap)[a][b][c] = NULL;
}
}
MDFN_free((*UsageMap)[a][b]);
(*UsageMap)[a][b] = NULL;
}
}
MDFN_free((*UsageMap)[a]);
(*UsageMap)[a] = NULL;
}
}
MDFN_free((*UsageMap));
(*UsageMap) = NULL;
}
}
void ASpace_ClearReadMap(const int id)
{
AddressSpaceType *as;
assert(id > 0 && (const unsigned int)id < AddressSpaces.size());
as = &AddressSpaces[id];
ClearUsageMap(&as->UsageMapRead);
as->UsageReadMemUsed = 0;
}
void ASpace_ClearWriteMap(const int id)
{
AddressSpaceType *as;
assert(id > 0 && (const unsigned int)id < AddressSpaces.size());
as = &AddressSpaces[id];
ClearUsageMap(&as->UsageMapWrite);
as->UsageWriteMemUsed = 0;
}
void MDFNDBG_ResetRegGroupsInfo(void)
{
RegGroups.clear();
}
void MDFNDBG_AddRegGroup(RegGroupType *groupie)
{
RegGroups.push_back(groupie);
}
void ASpace_Reset(void)
{
AddressSpaces.clear();
}
RegType::~RegType()
{
}
#endif