mirror of
https://github.com/SourMesen/Mesen.git
synced 2025-04-02 10:52:48 -04:00
Debugger: Performance improvements, code refactoring & code display changes/fixes
This commit is contained in:
parent
9da501bbd5
commit
80bd7d0b3e
9 changed files with 211 additions and 126 deletions
|
@ -470,13 +470,14 @@ bool Debugger::IsCodeChanged()
|
|||
string Debugger::GenerateOutput()
|
||||
{
|
||||
State cpuState = _cpu->GetState();
|
||||
std::ostringstream output;
|
||||
string output;
|
||||
output.reserve(10000);
|
||||
|
||||
bool showEffectiveAddresses = CheckFlag(DebuggerFlags::ShowEffectiveAddresses);
|
||||
bool showOnlyDiassembledCode = CheckFlag(DebuggerFlags::ShowOnlyDisassembledCode);
|
||||
|
||||
//Get code in internal RAM
|
||||
output << _disassembler->GetCode(0x0000, 0x1FFF, 0x0000, PrgMemoryType::PrgRom, showEffectiveAddresses, showOnlyDiassembledCode, cpuState, _memoryManager, _labelManager);
|
||||
output << "2000\x1\x1\x1--End of internal RAM--\n";
|
||||
output = _disassembler->GetCode(0x0000, 0x1FFF, 0x0000, PrgMemoryType::PrgRom, showEffectiveAddresses, showOnlyDiassembledCode, cpuState, _memoryManager, _labelManager);
|
||||
|
||||
for(uint32_t i = 0x2000; i < 0x10000; i += 0x100) {
|
||||
//Merge all sequential ranges into 1 chunk
|
||||
|
@ -497,11 +498,11 @@ string Debugger::GenerateOutput()
|
|||
addr += 0x100;
|
||||
i+=0x100;
|
||||
}
|
||||
output << _disassembler->GetCode(startAddr, endAddr, startMemoryAddr, memoryType, showEffectiveAddresses, showOnlyDiassembledCode, cpuState, _memoryManager, _labelManager);
|
||||
output += _disassembler->GetCode(startAddr, endAddr, startMemoryAddr, memoryType, showEffectiveAddresses, showOnlyDiassembledCode, cpuState, _memoryManager, _labelManager);
|
||||
}
|
||||
}
|
||||
|
||||
return output.str();
|
||||
return output;
|
||||
}
|
||||
|
||||
string* Debugger::GetCode()
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "MemoryManager.h"
|
||||
#include "CPU.h"
|
||||
#include "LabelManager.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
|
||||
Disassembler::Disassembler(uint8_t* internalRam, uint8_t* prgRom, uint32_t prgSize, uint8_t* prgRam, uint32_t prgRamSize)
|
||||
{
|
||||
|
@ -187,9 +188,47 @@ vector<string> Disassembler::SplitComment(string input)
|
|||
return result;
|
||||
}
|
||||
|
||||
string Disassembler::GetLine(string code, string comment, int32_t cpuAddress, int32_t absoluteAddress, string byteCode, string addressing)
|
||||
{
|
||||
string out;
|
||||
out.reserve(50);
|
||||
if(cpuAddress >= 0) {
|
||||
out += HexUtilities::ToHex((uint16_t)cpuAddress);
|
||||
}
|
||||
out += "\x1";
|
||||
if(absoluteAddress >= 0) {
|
||||
out += HexUtilities::ToHex((uint32_t)absoluteAddress);
|
||||
}
|
||||
out += "\x1" + byteCode + "\x1" + code + "\x2" + addressing + "\x2" + (comment.empty() ? "" : (";" + comment)) + "\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
string Disassembler::GetSubHeader(DisassemblyInfo *info, string &label, uint16_t relativeAddr, uint16_t resetVector, uint16_t nmiVector, uint16_t irqVector)
|
||||
{
|
||||
if(info->IsSubEntryPoint()) {
|
||||
if(label.empty()) {
|
||||
return GetLine() + GetLine("__sub start__");
|
||||
} else {
|
||||
return GetLine() + GetLine("__" + label + "()__");
|
||||
}
|
||||
} else if(relativeAddr == resetVector) {
|
||||
return GetLine() + GetLine("--reset--");
|
||||
} else if(relativeAddr == irqVector) {
|
||||
return GetLine() + GetLine("--irq--");
|
||||
} else if(relativeAddr == nmiVector) {
|
||||
return GetLine() + GetLine("--nmi--");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memoryAddr, PrgMemoryType memoryType, bool showEffectiveAddresses, bool showOnlyDiassembledCode, State& cpuState, shared_ptr<MemoryManager> memoryManager, shared_ptr<LabelManager> labelManager)
|
||||
{
|
||||
std::ostringstream output;
|
||||
string output;
|
||||
output.reserve(10000000);
|
||||
|
||||
int32_t dbRelativeAddr;
|
||||
int32_t dbAbsoluteAddr;
|
||||
string dbBuffer;
|
||||
|
||||
uint16_t resetVector = memoryManager->DebugReadWord(CPU::ResetVector);
|
||||
uint16_t nmiVector = memoryManager->DebugReadWord(CPU::NMIVector);
|
||||
|
@ -210,116 +249,90 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memo
|
|||
source = _prgRom;
|
||||
}
|
||||
|
||||
string unknownBlockHeader = showOnlyDiassembledCode ? "----" : "__unknown block__";
|
||||
uint32_t addr = startAddr;
|
||||
uint32_t byteCount = 0;
|
||||
bool skippingCode = false;
|
||||
while(addr <= endAddr) {
|
||||
string label = labelManager->GetLabel(memoryAddr, false);
|
||||
string commentString = labelManager->GetComment(memoryAddr);
|
||||
string labelString = label.empty() ? "" : ("\x1\x1\x1" + label + ":\n");
|
||||
bool multilineComment = commentString.find_first_of('\n') != string::npos;
|
||||
string singleLineComment = "";
|
||||
string multiLineComment = "";
|
||||
if(multilineComment) {
|
||||
string labelLine = label.empty() ? "" : GetLine(label + ":");
|
||||
string commentLines = "";
|
||||
if(commentString.find_first_of('\n') != string::npos) {
|
||||
for(string &str : SplitComment(commentString)) {
|
||||
multiLineComment += "\x1\x1\x1\x2\x2;" + str + "\n";
|
||||
commentLines += GetLine("", str);
|
||||
}
|
||||
} else if(!commentString.empty()) {
|
||||
singleLineComment = "\x2;" + commentString;
|
||||
commentString = "";
|
||||
}
|
||||
|
||||
shared_ptr<DisassemblyInfo> info = (*cache)[addr&mask];
|
||||
|
||||
if(info) {
|
||||
if(byteCount > 0) {
|
||||
output << "\n";
|
||||
output += GetLine(dbBuffer, "", dbRelativeAddr, dbAbsoluteAddr);
|
||||
byteCount = 0;
|
||||
}
|
||||
|
||||
if(skippingCode) {
|
||||
output << std::hex << std::uppercase << (memoryAddr - 1) << "\x1" << (addr - 1) << "\x1\x1";
|
||||
if(showOnlyDiassembledCode) {
|
||||
output << "----\n";
|
||||
} else {
|
||||
output << "__unknown block__\n";
|
||||
}
|
||||
output += GetLine(unknownBlockHeader, "", (uint16_t)(memoryAddr - 1), addr - 1);
|
||||
skippingCode = false;
|
||||
}
|
||||
|
||||
output += GetSubHeader(info.get(), label, memoryAddr, resetVector, nmiVector, irqVector);
|
||||
output += commentLines;
|
||||
output += labelLine;
|
||||
|
||||
string effectiveAddress = showEffectiveAddresses ? info->GetEffectiveAddressString(cpuState, memoryManager, labelManager) : "";
|
||||
|
||||
if(info->IsSubEntryPoint()) {
|
||||
if(label.empty()) {
|
||||
output << "\x1\x1\x1\n\x1\x1\x1__sub start__\n";
|
||||
} else {
|
||||
output << "\x1\x1\x1\n\x1\x1\x1__" + label + "()__\n";
|
||||
}
|
||||
} else if(memoryAddr == resetVector) {
|
||||
output << "\x1\x1\x1\n\x1\x1\x1--reset--\n";
|
||||
} else if(memoryAddr == irqVector) {
|
||||
output << "\x1\x1\x1\n\x1\x1\x1--irq--\n";
|
||||
} else if(memoryAddr == nmiVector) {
|
||||
output << "\x1\x1\x1\n\x1\x1\x1--nmi--\n";
|
||||
}
|
||||
|
||||
output << multiLineComment;
|
||||
output << labelString;
|
||||
output << std::hex << std::uppercase << memoryAddr << "\x1" << addr << "\x1" << info->GetByteCode() << "\x1 " << info->ToString(memoryAddr, memoryManager, labelManager) << "\x2" << effectiveAddress;
|
||||
output << singleLineComment;
|
||||
|
||||
output << "\n";
|
||||
output += GetLine(" " + info->ToString(memoryAddr, memoryManager, labelManager), commentString, memoryAddr, addr, info->GetByteCode(), effectiveAddress);
|
||||
|
||||
if(info->IsSubExitPoint()) {
|
||||
output << "\x1\x1\x1__sub end__\n\x1\x1\x1\n";
|
||||
output += GetLine("__sub end__") + GetLine();
|
||||
}
|
||||
|
||||
addr += info->GetSize();
|
||||
memoryAddr += info->GetSize();
|
||||
} else {
|
||||
if(!label.empty() && skippingCode) {
|
||||
output << std::hex << std::uppercase << (memoryAddr - 1) << "\x1" << (addr - 1) << "\x1\x1";
|
||||
if(showOnlyDiassembledCode) {
|
||||
output << "----\n";
|
||||
} else {
|
||||
output << "__unknown block__\n";
|
||||
}
|
||||
if((!label.empty() || !commentString.empty()) && skippingCode) {
|
||||
output += GetLine(unknownBlockHeader, "", (uint16_t)(memoryAddr - 1), addr - 1);
|
||||
skippingCode = false;
|
||||
}
|
||||
|
||||
if(!skippingCode) {
|
||||
output << std::hex << std::uppercase << memoryAddr << "\x1" << addr << "\x1\x1";
|
||||
if(showOnlyDiassembledCode) {
|
||||
if(label.empty()) {
|
||||
output << "__unknown block__\n";
|
||||
} else {
|
||||
output << "__" << label << "__\n";
|
||||
if(!singleLineComment.empty()) {
|
||||
output << "\x1\x1\x1\x2" << singleLineComment << "\n";
|
||||
} else {
|
||||
output << multiLineComment;
|
||||
}
|
||||
if(!skippingCode && showOnlyDiassembledCode) {
|
||||
if(label.empty()) {
|
||||
output += GetLine("__unknown block__", "", memoryAddr, addr);
|
||||
if(!commentString.empty()) {
|
||||
output += GetLine("", commentString);
|
||||
}
|
||||
} else {
|
||||
output << "--unknown block--\n";
|
||||
output += GetLine("__" + label + "__", "", memoryAddr, addr);
|
||||
if(!commentString.empty()) {
|
||||
output += GetLine("", commentString);
|
||||
}
|
||||
output += commentLines;
|
||||
}
|
||||
skippingCode = true;
|
||||
}
|
||||
|
||||
if(!showOnlyDiassembledCode) {
|
||||
if(byteCount >= 8 || !label.empty() || !commentString.empty()) {
|
||||
output << "\n";
|
||||
output += GetLine(dbBuffer, "", dbRelativeAddr, dbAbsoluteAddr);
|
||||
byteCount = 0;
|
||||
}
|
||||
if(byteCount == 0) {
|
||||
output << multiLineComment;
|
||||
output << labelString;
|
||||
output << std::hex << std::uppercase << memoryAddr << "\x1" << addr << "\x1\x1" << ".db";
|
||||
output << singleLineComment;
|
||||
|
||||
if(!label.empty() || !commentString.empty()) {
|
||||
byteCount = 7;
|
||||
}
|
||||
if(byteCount == 0) {
|
||||
dbBuffer = ".db";
|
||||
output += commentLines;
|
||||
output += labelLine;
|
||||
|
||||
dbRelativeAddr = memoryAddr;
|
||||
dbAbsoluteAddr = addr;
|
||||
}
|
||||
|
||||
dbBuffer += " $" + HexUtilities::ToHex(source[addr&mask]);
|
||||
|
||||
if(!label.empty() || !commentString.empty()) {
|
||||
output += GetLine(dbBuffer, commentString, dbRelativeAddr, dbAbsoluteAddr);
|
||||
}
|
||||
output << std::hex << " $" << std::setfill('0') << std::setw(2) << (short)source[addr&mask];
|
||||
|
||||
byteCount++;
|
||||
}
|
||||
|
@ -329,21 +342,14 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memo
|
|||
}
|
||||
|
||||
if(skippingCode) {
|
||||
if(byteCount != 0) {
|
||||
output << "\n";
|
||||
}
|
||||
|
||||
output << std::hex << std::uppercase << (memoryAddr - 1) << "\x1" << (addr - 1) << "\x1\x1";
|
||||
if(showOnlyDiassembledCode) {
|
||||
output << "----\n";
|
||||
} else {
|
||||
output << "__unknown block__\n";
|
||||
}
|
||||
}
|
||||
|
||||
output << "\n";
|
||||
if(showOnlyDiassembledCode && byteCount > 0) {
|
||||
output += GetLine(dbBuffer, "", dbRelativeAddr, dbAbsoluteAddr);
|
||||
}
|
||||
|
||||
return output.str();
|
||||
output += GetLine("----", "", (uint16_t)(memoryAddr - 1), addr - 1);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
shared_ptr<DisassemblyInfo> Disassembler::GetDisassemblyInfo(int32_t absoluteAddress, int32_t absoluteRamAddress, uint16_t memoryAddress)
|
||||
|
|
|
@ -20,6 +20,8 @@ private:
|
|||
|
||||
bool IsUnconditionalJump(uint8_t opCode);
|
||||
vector<string> SplitComment(string input);
|
||||
string GetLine(string code = "", string comment = "", int32_t cpuAddress = -1, int32_t absoluteAddress = -1, string byteCode = "", string addressing = "");
|
||||
string GetSubHeader(DisassemblyInfo *info, string &label, uint16_t relativeAddr, uint16_t resetVector, uint16_t nmiVector, uint16_t irqVector);
|
||||
|
||||
public:
|
||||
Disassembler(uint8_t* internalRam, uint8_t* prgRom, uint32_t prgSize, uint8_t* prgRam, uint32_t prgRamSize);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "DisassemblyInfo.h"
|
||||
#include "CPU.h"
|
||||
#include "LabelManager.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
|
||||
string DisassemblyInfo::OPName[256];
|
||||
AddrMode DisassemblyInfo::OPMode[256];
|
||||
|
@ -9,20 +10,26 @@ uint32_t DisassemblyInfo::OPSize[256];
|
|||
|
||||
string DisassemblyInfo::ToString(uint32_t memoryAddr, shared_ptr<MemoryManager> memoryManager, shared_ptr<LabelManager> labelManager)
|
||||
{
|
||||
std::ostringstream output;
|
||||
string out;
|
||||
out.reserve(50);
|
||||
|
||||
uint8_t opCode = *_opPointer;
|
||||
|
||||
output << DisassemblyInfo::OPName[opCode];
|
||||
if(DisassemblyInfo::OPName[opCode].empty()) {
|
||||
output << "invalid opcode";
|
||||
out = "invalid opcode";
|
||||
} else {
|
||||
out = DisassemblyInfo::OPName[opCode];
|
||||
}
|
||||
|
||||
std::ostringstream addrString;
|
||||
if(_opSize == 2) {
|
||||
_opAddr = *(_opPointer + 1);
|
||||
} else if(_opSize == 3) {
|
||||
_opAddr = *(_opPointer + 1) | (*(_opPointer + 2) << 8);
|
||||
}
|
||||
|
||||
if(_opMode == AddrMode::Rel) {
|
||||
_opAddr = (int8_t)_opAddr + memoryAddr + 2;
|
||||
}
|
||||
|
||||
string operandValue;
|
||||
if(labelManager && _opMode != AddrMode::Imm) {
|
||||
|
@ -30,50 +37,48 @@ string DisassemblyInfo::ToString(uint32_t memoryAddr, shared_ptr<MemoryManager>
|
|||
}
|
||||
|
||||
if(operandValue.empty()) {
|
||||
std::stringstream ss;
|
||||
ss << "$" << std::uppercase << std::hex << std::setw(_opSize == 2 ? 2 : 4) << std::setfill('0') << (short)_opAddr;
|
||||
operandValue = ss.str();
|
||||
if(_opSize == 2) {
|
||||
operandValue += "$" + HexUtilities::ToHex((uint8_t)_opAddr);
|
||||
} else {
|
||||
operandValue += "$" + HexUtilities::ToHex((uint16_t)_opAddr);
|
||||
}
|
||||
}
|
||||
|
||||
output << " ";
|
||||
out += " ";
|
||||
|
||||
switch(_opMode) {
|
||||
case AddrMode::Acc: output << "A"; break;
|
||||
case AddrMode::Imm: output << "#" << operandValue; break;
|
||||
case AddrMode::Ind: output << "(" << operandValue << ")"; break;
|
||||
case AddrMode::IndX: output << "(" << operandValue << ",X)"; break;
|
||||
case AddrMode::Acc: out += "A"; break;
|
||||
case AddrMode::Imm: out += "#" + operandValue; break;
|
||||
case AddrMode::Ind: out += "(" + operandValue + ")"; break;
|
||||
case AddrMode::IndX: out += "(" + operandValue + ",X)"; break;
|
||||
|
||||
case AddrMode::IndY:
|
||||
case AddrMode::IndYW:
|
||||
output << "(" << operandValue << "),Y";
|
||||
out += "(" + operandValue + "),Y";
|
||||
break;
|
||||
|
||||
case AddrMode::Abs:
|
||||
case AddrMode::Rel:
|
||||
case AddrMode::Zero:
|
||||
output << operandValue;
|
||||
out += operandValue;
|
||||
break;
|
||||
|
||||
case AddrMode::AbsX:
|
||||
case AddrMode::AbsXW:
|
||||
case AddrMode::ZeroX:
|
||||
output << operandValue << ",X";
|
||||
out += operandValue + ",X";
|
||||
break;
|
||||
|
||||
case AddrMode::AbsY:
|
||||
case AddrMode::AbsYW:
|
||||
case AddrMode::ZeroY:
|
||||
output << operandValue << ",Y";
|
||||
break;
|
||||
|
||||
case AddrMode::Rel:
|
||||
//TODO (not correct when banks are switched around in memory)
|
||||
output << "$" << std::uppercase << std::hex << std::setw(2) << std::setfill('0') << ((int8_t)*(_opPointer + 1) + memoryAddr + 2);
|
||||
out += operandValue + ",Y";
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
return output.str();
|
||||
return out;
|
||||
}
|
||||
|
||||
DisassemblyInfo::DisassemblyInfo(uint8_t* opPointer, bool isSubEntryPoint)
|
||||
|
@ -86,21 +91,20 @@ DisassemblyInfo::DisassemblyInfo(uint8_t* opPointer, bool isSubEntryPoint)
|
|||
_opMode = DisassemblyInfo::OPMode[opCode];
|
||||
_isSubExitPoint = opCode == 0x40 || opCode == 0x60;
|
||||
|
||||
|
||||
//Raw byte code
|
||||
std::stringstream byteCodeOutput;
|
||||
string byteCodeOutput;
|
||||
byteCodeOutput.reserve(10);
|
||||
for(uint32_t i = 0; i < 3; i++) {
|
||||
if(i < _opSize) {
|
||||
byteCodeOutput << "$" << std::hex << std::uppercase << std::setfill('0') << std::setw(2) << (short)*(_opPointer + i);
|
||||
byteCodeOutput += "$" + HexUtilities::ToHex((uint16_t)*(_opPointer + i));
|
||||
} else {
|
||||
byteCodeOutput << " ";
|
||||
byteCodeOutput += " ";
|
||||
}
|
||||
if(i != 2) {
|
||||
byteCodeOutput << " ";
|
||||
byteCodeOutput += " ";
|
||||
}
|
||||
}
|
||||
_byteCode = byteCodeOutput.str();
|
||||
|
||||
_byteCode = byteCodeOutput;
|
||||
}
|
||||
|
||||
void DisassemblyInfo::SetSubEntryPoint()
|
||||
|
@ -122,15 +126,15 @@ string DisassemblyInfo::GetEffectiveAddressString(State& cpuState, shared_ptr<Me
|
|||
}
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::uppercase << std::setfill('0') << " @ $";
|
||||
string output;
|
||||
output = " @ $";
|
||||
if(_opMode == AddrMode::ZeroX || _opMode == AddrMode::ZeroY) {
|
||||
ss << std::setw(2) << std::hex << (uint16_t)effectiveAddress;
|
||||
output += HexUtilities::ToHex((uint8_t)effectiveAddress);
|
||||
} else {
|
||||
ss << std::setw(4) << std::hex << (uint16_t)effectiveAddress;
|
||||
output += HexUtilities::ToHex((uint16_t)effectiveAddress);
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "Console.h"
|
||||
#include "Debugger.h"
|
||||
#include "LabelManager.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
|
||||
std::unordered_map<string, std::vector<int>, StringHasher> ExpressionEvaluator::_outputCache;
|
||||
SimpleLock ExpressionEvaluator::_cacheLock;
|
||||
|
@ -164,11 +165,7 @@ string ExpressionEvaluator::GetNextToken(string expression, size_t &pos)
|
|||
}
|
||||
|
||||
if(isHex) {
|
||||
unsigned int x;
|
||||
std::stringstream ss;
|
||||
ss << std::hex << output;
|
||||
ss >> x;
|
||||
output = std::to_string(x);
|
||||
output = std::to_string(HexUtilities::FromHex(output));
|
||||
}
|
||||
|
||||
return output;
|
||||
|
|
52
Utilities/HexUtilities.cpp
Normal file
52
Utilities/HexUtilities.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
#include "stdafx.h"
|
||||
#include "HexUtilities.h"
|
||||
|
||||
const vector<string> HexUtilities::_hexCache = { {
|
||||
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
|
||||
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
|
||||
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
|
||||
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
|
||||
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
|
||||
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
|
||||
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
|
||||
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
|
||||
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
|
||||
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
|
||||
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
|
||||
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
|
||||
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
|
||||
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
|
||||
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
|
||||
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF"
|
||||
} };
|
||||
|
||||
int HexUtilities::FromHex(string hex)
|
||||
{
|
||||
int value = 0;
|
||||
for(size_t i = 0, len = hex.size(); i < len; i++) {
|
||||
value <<= 4;
|
||||
if(hex[i] >= '0' && hex[i] <= '9') {
|
||||
value |= hex[i] - '0';
|
||||
} else if(hex[i] >= 'A' && hex[i] <= 'F') {
|
||||
value |= hex[i] - 'A' + 10;
|
||||
} else if(hex[i] >= 'a' && hex[i] <= 'f') {
|
||||
value |= hex[i] - 'a' + 10;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
string HexUtilities::ToHex(uint8_t value)
|
||||
{
|
||||
return _hexCache[value];
|
||||
}
|
||||
|
||||
string HexUtilities::ToHex(uint16_t value)
|
||||
{
|
||||
return _hexCache[value >> 8] + _hexCache[value & 0xFF];
|
||||
}
|
||||
|
||||
string HexUtilities::ToHex(uint32_t value)
|
||||
{
|
||||
return _hexCache[value >> 24] + _hexCache[(value >> 16) & 0xFF] + _hexCache[(value >> 8) & 0xFF] + _hexCache[value & 0xFF];
|
||||
}
|
15
Utilities/HexUtilities.h
Normal file
15
Utilities/HexUtilities.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
|
||||
class HexUtilities
|
||||
{
|
||||
private:
|
||||
const static vector<string> _hexCache;
|
||||
|
||||
public:
|
||||
static string ToHex(uint8_t addr);
|
||||
static string ToHex(uint16_t addr);
|
||||
static string ToHex(uint32_t addr);
|
||||
|
||||
static int FromHex(string hex);
|
||||
};
|
|
@ -325,6 +325,7 @@
|
|||
<ClInclude Include="blip_buf.h" />
|
||||
<ClInclude Include="CRC32.h" />
|
||||
<ClInclude Include="FolderUtilities.h" />
|
||||
<ClInclude Include="HexUtilities.h" />
|
||||
<ClInclude Include="HQX\common.h" />
|
||||
<ClInclude Include="HQX\hqx.h" />
|
||||
<ClInclude Include="IpsPatcher.h" />
|
||||
|
@ -359,6 +360,7 @@
|
|||
<ClCompile Include="blip_buf.cpp" />
|
||||
<ClCompile Include="CRC32.cpp" />
|
||||
<ClCompile Include="FolderUtilities.cpp" />
|
||||
<ClCompile Include="HexUtilities.cpp" />
|
||||
<ClCompile Include="HQX\hq2x.cpp" />
|
||||
<ClCompile Include="HQX\hq3x.cpp" />
|
||||
<ClCompile Include="HQX\hq4x.cpp" />
|
||||
|
|
|
@ -119,6 +119,9 @@
|
|||
<ClInclude Include="PlatformUtilities.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HexUtilities.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
@ -214,5 +217,8 @@
|
|||
<ClCompile Include="PlatformUtilities.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HexUtilities.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Add table
Reference in a new issue