Compare commits
10 commits
Author | SHA1 | Date | |
---|---|---|---|
DataHoarder | 875f6588d9 | ||
DataHoarder | 3868034b6b | ||
DataHoarder | 812d1d632f | ||
DataHoarder | 926b1d6a82 | ||
DataHoarder | 83a1b7d280 | ||
DataHoarder | b019ab7684 | ||
DataHoarder | 6a5d9696e7 | ||
DataHoarder | 6d3760c96e | ||
DataHoarder | 2324a561f3 | ||
DataHoarder | bf7c3cefe5 |
|
@ -238,7 +238,7 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
|
|||
if ((instruction->getCommand() == Instruction::Instruction::CommandOp::JUMP ||
|
||||
instruction->getCommand() == Instruction::Instruction::CommandOp::RETURN) &&
|
||||
jumpsUsed.find(instruction->getEndAddress()) == jumpsUsed.end()) {
|
||||
jumpsUsed[instruction->getEndAddress()] = false;
|
||||
jumpsUsed[instruction->getEndAddress()] = false; //TODO: remove this or make it opt-in by default
|
||||
}
|
||||
|
||||
if (jumpsUsed.find(state.current) != jumpsUsed.end() && !jumpsUsed[state.current]) {
|
||||
|
|
|
@ -52,6 +52,10 @@ std::string OutputContext::getComment(uint32_t location) const {
|
|||
return "";
|
||||
}
|
||||
|
||||
bool OutputContext::isNop(uint32_t location) const {
|
||||
return nop.find(location) != nop.end();
|
||||
}
|
||||
|
||||
|
||||
std::string OutputContext::getDataHeader(uint32_t location) const {
|
||||
std::stringstream s;
|
||||
|
@ -150,7 +154,7 @@ void OutputContext::analyze() {
|
|||
if (writeInstruction.data.size() == 1 &&
|
||||
writeInstruction.data[0] == e.first) { //Return value!
|
||||
//TODO: mark join?
|
||||
addComment(writeInstruction.getAddress() + 4, locText);
|
||||
addComment(writeInstruction.getAddress() + 4, locText, true);
|
||||
foundReturn = true;
|
||||
break;
|
||||
}
|
||||
|
@ -172,7 +176,7 @@ void OutputContext::analyze() {
|
|||
}
|
||||
|
||||
if (e.second.size() > 1 || (!hasContinue && !e.second.empty())) {
|
||||
addComment(e.first, "<" + getLabel(e.first, true) + "> " + from.str());
|
||||
addComment(e.first, "<" + getLabel(e.first, true) + "> " + from.str(), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,19 +188,29 @@ void OutputContext::addMapping(uint32_t location, const std::string &name, bool
|
|||
}
|
||||
}
|
||||
|
||||
void OutputContext::addComment(uint32_t location, const std::string &comment) {
|
||||
void OutputContext::addComment(uint32_t location, const std::string &comment, bool force) {
|
||||
|
||||
if (comments.find(location) != comments.end()) {
|
||||
comments[location] = comment + " --- " + comments[location];
|
||||
comments[location] = force ? comment + " :: " + comments[location] : comments[location] + " :: " + comment;
|
||||
} else {
|
||||
comments[location] = comment;
|
||||
}
|
||||
}
|
||||
|
||||
void OutputContext::setNop(uint32_t location) {
|
||||
|
||||
nop[location] = true;
|
||||
}
|
||||
|
||||
std::string OutputContext::getAddressRegisterName(uint32_t addr, uint8_t offset) const {
|
||||
if (offset || registers.find(addr) == registers.end()) {
|
||||
uint64_t k = (uint64_t)addr | ((uint64_t)offset << 32);
|
||||
if (registers.find(k) == registers.end()) {
|
||||
return ::getAddressRegisterName(addr, offset);
|
||||
} else {
|
||||
return registers.at(addr);
|
||||
return registers.at(k);
|
||||
}
|
||||
}
|
||||
|
||||
void OutputContext::addRegister(const Instruction::AddressWithOffset &address, const std::string &name) {
|
||||
registers[(uint64_t)address.address | ((uint64_t)address.offset << 32)] = name;
|
||||
}
|
||||
|
|
|
@ -41,21 +41,22 @@ private:
|
|||
const ImageFormat ℑ
|
||||
std::unordered_map<uint32_t, std::string> mappings;
|
||||
std::unordered_map<uint32_t, std::string> comments;
|
||||
std::unordered_map<uint32_t, std::string> registers;
|
||||
std::unordered_map<uint64_t, std::string> registers;
|
||||
std::unordered_map<uint32_t, bool> nop;
|
||||
|
||||
public:
|
||||
|
||||
OutputContext(const ImageFormat &image) : image(image) {
|
||||
explicit OutputContext(const ImageFormat &image) : image(image) {
|
||||
|
||||
}
|
||||
|
||||
void addMapping(uint32_t location, const std::string &name, bool force = false);
|
||||
|
||||
void addComment(uint32_t location, const std::string &comment);
|
||||
void addComment(uint32_t location, const std::string &comment, bool force = false);
|
||||
|
||||
void addRegister(uint32_t addr, const std::string &name) {
|
||||
registers[addr] = name;
|
||||
}
|
||||
void setNop(uint32_t location);
|
||||
|
||||
void addRegister(const Instruction::AddressWithOffset& address, const std::string &name);
|
||||
|
||||
std::string getAddressRegisterName(uint32_t addr, uint8_t offset) const;
|
||||
|
||||
|
@ -69,6 +70,8 @@ public:
|
|||
|
||||
std::string getDataHeader(uint32_t location) const;
|
||||
|
||||
bool isNop(uint32_t location) const;
|
||||
|
||||
std::string getDataEntry(uint32_t location, const std::string &representation = "") const;
|
||||
|
||||
std::string getInstructionString(const Instruction::Instruction &instruction) const;
|
||||
|
|
|
@ -180,7 +180,7 @@ Instruction::Calc::execute(AnalysisState &state) const {
|
|||
|
||||
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
|
||||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::Calc::toBytes() const {
|
||||
|
|
|
@ -179,7 +179,7 @@ Instruction::CalcImm::execute(AnalysisState &state) const {
|
|||
|
||||
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
|
||||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::CalcImm::toBytes() const {
|
||||
|
|
|
@ -91,7 +91,7 @@ Instruction::Copy::execute(AnalysisState &state) const {
|
|||
|
||||
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
|
||||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,14 +52,14 @@ std::vector<Instruction::OutputFormat> Instruction::End::toOutputFormat(const Ou
|
|||
}
|
||||
|
||||
std::vector<uint32_t> Instruction::End::getPossibleBranches() const {
|
||||
return std::vector<uint32_t>();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::End::execute(AnalysisState &state) const {
|
||||
state.current = 0;
|
||||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::End::toBytes() const {
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "../Registers.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include "../OutputContext.h"
|
||||
|
||||
void Instruction::Init::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
|
||||
_address = offset;
|
||||
|
@ -69,18 +70,35 @@ std::string Instruction::Init::toString() const {
|
|||
if (count > 1 && increment) {
|
||||
op << " UNTIL " << getAddressRegisterName(address + count - 1, addressOffset);
|
||||
}
|
||||
op << " COUNT " << std::hex << std::setw(6) << std::setfill('0') << count;
|
||||
op << " INCREMENT " << std::dec << (uint32_t) increment;
|
||||
op << " COUNT " << std::hex << std::setw(6) << std::setfill('0') << count;
|
||||
op << " DATA 0x" << std::hex << std::setw(8) << std::setfill('0') << data;
|
||||
op << " INC 0x" << std::hex << std::setw(8) << std::setfill('0') << data_add;
|
||||
op << " ADD 0x" << std::hex << std::setw(8) << std::setfill('0') << data_add;
|
||||
|
||||
return op.str();
|
||||
}
|
||||
|
||||
std::vector<Instruction::OutputFormat> Instruction::Init::toOutputFormat(const OutputContext &context) const {
|
||||
return std::vector<OutputFormat>{
|
||||
//TODO
|
||||
std::vector<OutputFormat> f{
|
||||
OutputFormat{getAddress() + 0 * 4,
|
||||
dynamic_cast<std::stringstream &>(std::stringstream("") << "INIT" << " "
|
||||
<< context.getAddressRegisterName(
|
||||
address, addressOffset)
|
||||
<< ", INC " << std::dec
|
||||
<< (uint32_t) increment).str()}
|
||||
};
|
||||
|
||||
f.emplace_back(OutputFormat{getAddress() + 1 * 4,
|
||||
dynamic_cast<std::stringstream &>(std::stringstream("") << " COUNT " << std::dec
|
||||
<< count).str()});
|
||||
|
||||
f.emplace_back(OutputFormat{getAddress() + 2 * 4,
|
||||
dynamic_cast<std::stringstream &>(std::stringstream("") << " DATA 0x" << std::hex << std::setw(8) << std::setfill('0') << data).str()});
|
||||
|
||||
f.emplace_back(OutputFormat{getAddress() + 3 * 4,
|
||||
dynamic_cast<std::stringstream &>(std::stringstream("") << " ADD 0x" << std::hex << std::setw(8) << std::setfill('0') << data_add).str()});
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> Instruction::Init::getPossibleBranches() const {
|
||||
|
@ -90,14 +108,14 @@ std::vector<uint32_t> Instruction::Init::getPossibleBranches() const {
|
|||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::Init::execute(AnalysisState &state) const {
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
state.setRegister(address + (increment ? i : 0), data + data_add * i);
|
||||
state.setRegister(address + increment, data + data_add * i);
|
||||
}
|
||||
|
||||
state.current = _endAddress;
|
||||
|
||||
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
|
||||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::Init::toBytes() const {
|
||||
|
|
|
@ -54,11 +54,11 @@ namespace Instruction {
|
|||
execute(AnalysisState &state) const override;
|
||||
|
||||
|
||||
uint8_t addressOffset;
|
||||
uint8_t increment;
|
||||
uint32_t address;
|
||||
uint32_t count;
|
||||
uint32_t data;
|
||||
uint32_t data_add;
|
||||
uint8_t addressOffset{};
|
||||
uint8_t increment{};
|
||||
uint32_t address{};
|
||||
uint32_t count{};
|
||||
uint32_t data{};
|
||||
uint32_t data_add{};
|
||||
};
|
||||
}
|
|
@ -48,6 +48,8 @@ namespace Instruction {
|
|||
uint32_t _endAddress{};
|
||||
public:
|
||||
|
||||
virtual ~Instruction()= default;
|
||||
|
||||
enum class CommandOp : uint8_t {
|
||||
WRITE = 0b00000000,
|
||||
COPY = 0b01000000,
|
||||
|
|
|
@ -70,7 +70,7 @@ Instruction::Jump::execute(AnalysisState &state) const {
|
|||
|
||||
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Absolute);
|
||||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::Jump::toBytes() const {
|
||||
|
|
|
@ -220,7 +220,7 @@ Instruction::Load::execute(AnalysisState &state) const {
|
|||
|
||||
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
|
||||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::Load::toBytes() const {
|
||||
|
|
|
@ -63,7 +63,7 @@ std::vector<Instruction::OutputFormat> Instruction::Return::toOutputFormat(const
|
|||
}
|
||||
|
||||
std::vector<uint32_t> Instruction::Return::getPossibleBranches() const {
|
||||
return std::vector<uint32_t>();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
|
@ -73,7 +73,7 @@ Instruction::Return::execute(AnalysisState &state) const {
|
|||
|
||||
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Return);
|
||||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ Instruction::Set::execute(AnalysisState &state) const {
|
|||
|
||||
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
|
||||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::Set::toBytes() const {
|
||||
|
|
|
@ -70,7 +70,7 @@ Instruction::Wait::execute(AnalysisState &state) const {
|
|||
|
||||
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
|
||||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::Wait::toBytes() const {
|
||||
|
|
|
@ -36,7 +36,7 @@ void Instruction::Write::fromBytes(uint32_t offset, const std::vector<uint8_t> &
|
|||
|
||||
uint32_t command = bytes[offset++];
|
||||
|
||||
uint8_t count = (1 + (command >> 2) & 0b1111);
|
||||
uint8_t count = (1 + ((command >> 2) & 0b1111));
|
||||
address.offset = command & 0b11;
|
||||
|
||||
address.address = bytes[offset++] << 16;
|
||||
|
@ -108,7 +108,7 @@ Instruction::Write::execute(AnalysisState &state) const {
|
|||
|
||||
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
|
||||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::Write::toBytes() const {
|
||||
|
|
241
src/main.cpp
241
src/main.cpp
|
@ -36,6 +36,23 @@
|
|||
#include "OutputContext.h"
|
||||
#include "instructions/End.h"
|
||||
|
||||
|
||||
std::string ltrim(const std::string &s)
|
||||
{
|
||||
size_t start = s.find_first_not_of(" \n\r\t\f\v");
|
||||
return (start == std::string::npos) ? "" : s.substr(start);
|
||||
}
|
||||
|
||||
std::string rtrim(const std::string &s)
|
||||
{
|
||||
size_t end = s.find_last_not_of(" \n\r\t\f\v");
|
||||
return (end == std::string::npos) ? "" : s.substr(0, end + 1);
|
||||
}
|
||||
|
||||
std::string trim(const std::string &s) {
|
||||
return rtrim(ltrim(s));
|
||||
}
|
||||
|
||||
void decodeImage(const std::string &fileName) {
|
||||
|
||||
std::ifstream image(fileName);
|
||||
|
@ -47,7 +64,7 @@ void decodeImage(const std::string &fileName) {
|
|||
auto imageObject = ImageFormat::fromBytes(bytes);
|
||||
|
||||
|
||||
printf("SPEED: 0x%02x MODE: 0x%02x BOOT: 0x%08x\n", imageObject.getHeader().speed, imageObject.getHeader().mode,
|
||||
printf("SPEED: 0x%02x MODE: 0x%02x BOOT: 0x%08x\n", static_cast<uint32_t>(imageObject.getHeader().speed), static_cast<uint32_t>(imageObject.getHeader().mode),
|
||||
imageObject.getHeader().baseAddress);
|
||||
|
||||
std::cout << "SIGNATURE: " << imageObject.imageSignature << "\n";
|
||||
|
@ -299,80 +316,6 @@ void decodeImage(const std::string &fileName) {
|
|||
|
||||
};
|
||||
|
||||
|
||||
|
||||
bool isKnownAssembler = false;
|
||||
if (imageObject.imageSignature.find("rrc-as") != std::string::npos) {
|
||||
//Known assembler
|
||||
isKnownAssembler = true;
|
||||
comments.clear();
|
||||
knownNames.clear();
|
||||
|
||||
for (auto& i : imageObject.getInstructions()){
|
||||
std::unique_ptr<Instruction::Instruction> decodedInstruction = nullptr;
|
||||
std::unique_ptr<Instruction::Instruction> decodedInstruction2 = nullptr;
|
||||
const Instruction::End* endPointer = nullptr;
|
||||
if(i.second->getCommand() == Instruction::Instruction::CommandOp::END){
|
||||
endPointer = reinterpret_cast<const Instruction::End*>(i.second.get());
|
||||
if(endPointer->reserved == 0 || endPointer->reserved == 0xFFFFFF){
|
||||
endPointer = nullptr;
|
||||
}
|
||||
}
|
||||
if(endPointer == nullptr && imageObject.findConstInstructionByAddress(i.second->getEndAddress(), false) == nullptr){
|
||||
decodedInstruction = Instruction::Instruction::decodeInstructionFromBytes(i.second->getEndAddress(), imageObject.getBaseImage());
|
||||
if(decodedInstruction != nullptr && decodedInstruction->getCommand() == Instruction::Instruction::CommandOp::END){
|
||||
endPointer = reinterpret_cast<const Instruction::End*>(decodedInstruction.get());
|
||||
if(endPointer->reserved == 0 || endPointer->reserved == 0xFFFFFF){
|
||||
endPointer = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(endPointer != nullptr){ //Found backwards pointer
|
||||
decodedInstruction2 = Instruction::Instruction::decodeInstructionFromBytes(endPointer->getEndAddress(), imageObject.getBaseImage());
|
||||
if(decodedInstruction2 != nullptr && decodedInstruction2->getCommand() == Instruction::Instruction::CommandOp::LOAD){
|
||||
auto loadPointer = reinterpret_cast<const Instruction::Load&>(*decodedInstruction2);
|
||||
if(!loadPointer.increment && loadPointer.addressOffset == 0 && loadPointer.address == endPointer->getAddress()){ //found Function name
|
||||
uint32_t functionStart = endPointer->reserved;
|
||||
uint32_t functionEnd = loadPointer.address - 4;
|
||||
std::string functionName;
|
||||
for(auto& d : loadPointer.data){
|
||||
uint8_t c = ((d >> 24) & 0xFF);
|
||||
if(c == 0){
|
||||
break;
|
||||
}
|
||||
functionName.push_back(c);
|
||||
c = ((d >> 16) & 0xFF);
|
||||
if(c == 0){
|
||||
break;
|
||||
}
|
||||
functionName.push_back(c);
|
||||
c = ((d >> 8) & 0xFF);
|
||||
if(c == 0){
|
||||
break;
|
||||
}
|
||||
functionName.push_back(c);
|
||||
c = (d & 0xFF);
|
||||
if(c == 0){
|
||||
break;
|
||||
}
|
||||
functionName.push_back(c);
|
||||
}
|
||||
knownNames[functionStart] = functionName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &e : knownNames) {
|
||||
ctx.addMapping(e.first, e.second);
|
||||
}
|
||||
|
||||
for (auto &c : comments) {
|
||||
ctx.addComment(c.first, c.second);
|
||||
}
|
||||
|
||||
for(uint32_t i = 10; i < 200; ++i){
|
||||
if(registerRename.find((uint32_t) KnownRegisters::BSM_SCRATCH_START + i) == registerRename.end()){
|
||||
std::stringstream s;
|
||||
|
@ -406,7 +349,145 @@ void decodeImage(const std::string &fileName) {
|
|||
}
|
||||
|
||||
for (auto &r : registerRename) {
|
||||
ctx.addRegister(r.first, r.second);
|
||||
ctx.addRegister(Instruction::AddressWithOffset{r.first, 0}, r.second);
|
||||
}
|
||||
|
||||
bool isKnownAssembler = false;
|
||||
if (imageObject.imageSignature.find("rrc-as") != std::string::npos) {
|
||||
//Known assembler
|
||||
isKnownAssembler = true;
|
||||
comments.clear();
|
||||
knownNames.clear();
|
||||
|
||||
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_ADDR_OFFSET_3), 0}, "rrcc_STACK_POINTER");
|
||||
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_ADDR_OFFSET_2), 0}, "rrcc_FRAME_POINTER");
|
||||
|
||||
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::MGMT_SCRATCH_0), 0}, "rrcc_SCRATCH_0");
|
||||
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::MGMT_SCRATCH_1), 0}, "rrcc_SCRATCH_1");
|
||||
|
||||
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_SCRATCH_START) + 0x1E0, 0}, "rrcc_RETURN_VALUE");
|
||||
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_SCRATCH_START) + 0x1E1, 0}, "rrcc_RETURN_VALUE_EXTRA");
|
||||
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_SCRATCH_START) + 0x1E2, 0}, "rrcc_P0");
|
||||
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_SCRATCH_START) + 0x1E3, 0}, "rrcc_P1");
|
||||
|
||||
for(uint32_t i = 0; i < 16; ++i){
|
||||
ctx.addRegister(Instruction::AddressWithOffset{i, 3}, "rrcc_STACK_POINTER+" +
|
||||
std::to_string(i));
|
||||
}
|
||||
for(uint32_t i = 0; i < 16; ++i){
|
||||
ctx.addRegister(Instruction::AddressWithOffset{i, 2}, "rrcc_FRAME_POINTER+" +
|
||||
std::to_string(i));
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < 16; ++i){
|
||||
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_SCRATCH_START) + 0x1F0 + i, 0}, "rrcc_R" +
|
||||
std::to_string(i));
|
||||
}
|
||||
|
||||
|
||||
for (auto& i : imageObject.getInstructions()){
|
||||
std::unique_ptr<Instruction::Instruction> decodedInstruction = nullptr;
|
||||
std::unique_ptr<Instruction::Instruction> decodedInstruction2 = nullptr;
|
||||
const Instruction::End* endPointer = nullptr;
|
||||
if(i.second->getCommand() == Instruction::Instruction::CommandOp::END){
|
||||
endPointer = reinterpret_cast<const Instruction::End*>(i.second.get());
|
||||
if(endPointer->reserved == 0 || endPointer->reserved == 0xFFFFFF){
|
||||
endPointer = nullptr;
|
||||
}
|
||||
}
|
||||
if(endPointer == nullptr && imageObject.findConstInstructionByAddress(i.second->getEndAddress(), false) == nullptr){
|
||||
decodedInstruction = Instruction::Instruction::decodeInstructionFromBytes(i.second->getEndAddress(), imageObject.getBaseImage());
|
||||
if(decodedInstruction != nullptr && decodedInstruction->getCommand() == Instruction::Instruction::CommandOp::END){
|
||||
endPointer = reinterpret_cast<const Instruction::End*>(decodedInstruction.get());
|
||||
if(endPointer->reserved != endPointer->getAddress()){
|
||||
endPointer = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(endPointer != nullptr){ //Found backwards pointer
|
||||
bool hasMore = true;
|
||||
|
||||
ctx.setNop(endPointer->getAddress());
|
||||
|
||||
uint32_t functionEnd = endPointer->reserved - 4;
|
||||
uint32_t nextAddress = endPointer->getEndAddress();
|
||||
|
||||
do{
|
||||
decodedInstruction2 = Instruction::Instruction::decodeInstructionFromBytes(nextAddress, imageObject.getBaseImage());
|
||||
if(decodedInstruction2 != nullptr && decodedInstruction2->getCommand() == Instruction::Instruction::CommandOp::LOAD){
|
||||
auto loadPointer = reinterpret_cast<const Instruction::Load&>(*decodedInstruction2);
|
||||
for(auto nopAddr = loadPointer.getAddress(); nopAddr < loadPointer.getEndAddress(); nopAddr += 4){
|
||||
ctx.setNop(nopAddr);
|
||||
}
|
||||
|
||||
uint32_t targetAddress = loadPointer.address;
|
||||
std::string stringData;
|
||||
for(auto& d : loadPointer.data){
|
||||
uint8_t c = ((d >> 24) & 0xFF);
|
||||
if(c == 0){
|
||||
break;
|
||||
}
|
||||
stringData.push_back(c);
|
||||
c = ((d >> 16) & 0xFF);
|
||||
if(c == 0){
|
||||
break;
|
||||
}
|
||||
stringData.push_back(c);
|
||||
c = ((d >> 8) & 0xFF);
|
||||
if(c == 0){
|
||||
break;
|
||||
}
|
||||
stringData.push_back(c);
|
||||
c = (d & 0xFF);
|
||||
if(c == 0){
|
||||
break;
|
||||
}
|
||||
stringData.push_back(c);
|
||||
}
|
||||
|
||||
switch (loadPointer.addressOffset) {
|
||||
case 0: //FunctionName
|
||||
knownNames[targetAddress] = stringData;
|
||||
break;
|
||||
case 1: //Comment
|
||||
std::string s = stringData;
|
||||
size_t pos = 0;
|
||||
std::string token;
|
||||
while ((pos = s.find('\n')) != std::string::npos) {
|
||||
token = s.substr(0, pos);
|
||||
auto trimmed = trim(token);
|
||||
if(!trimmed.empty()){
|
||||
ctx.addComment(targetAddress, trimmed);
|
||||
}
|
||||
s.erase(0, pos + 1);
|
||||
}
|
||||
auto trimmed = trim(s);
|
||||
if(!trimmed.empty()){
|
||||
ctx.addComment(targetAddress, trimmed);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
nextAddress = loadPointer.getEndAddress();
|
||||
|
||||
hasMore = loadPointer.increment == 1;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
} while (hasMore);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &e : knownNames) {
|
||||
ctx.addMapping(e.first, e.second);
|
||||
}
|
||||
|
||||
for (auto &c : comments) {
|
||||
ctx.addComment(c.first, c.second);
|
||||
}
|
||||
|
||||
ctx.analyze();
|
||||
|
@ -414,7 +495,9 @@ void decodeImage(const std::string &fileName) {
|
|||
uint32_t prevAddress = 0;
|
||||
for (const auto &entry : imageObject.getInstructions()) {
|
||||
const auto &instruction = entry.second;
|
||||
if (instruction->getAddress() < prevAddress) {
|
||||
if(ctx.isNop(instruction->getAddress())){
|
||||
continue;
|
||||
}else if (instruction->getAddress() < prevAddress) {
|
||||
std::cout << "========== DECODE ERROR? ========== " << std::hex << std::setw(8) << std::setfill('0')
|
||||
<< prevAddress << " - " << std::hex << std::setw(8) << std::setfill('0')
|
||||
<< instruction->getAddress() << "\n";
|
||||
|
@ -422,6 +505,10 @@ void decodeImage(const std::string &fileName) {
|
|||
(instruction->getAddress() - prevAddress) < 1024) {
|
||||
std::cout << "\n\n";
|
||||
for (uint32_t addr = prevAddress; addr < instruction->getAddress(); addr += 4) {
|
||||
if(ctx.isNop(addr)){
|
||||
continue;
|
||||
}
|
||||
|
||||
std::stringstream op;
|
||||
std::string printable;
|
||||
op << std::hex << std::setw(6) << std::setfill('0') << addr << " ";
|
||||
|
|
Loading…
Reference in a new issue