Split VMA handling
Move VMA handling from memorymanip.cpp to bsnes.cpp
This commit is contained in:
parent
e42ce000cb
commit
a59650b11d
8 changed files with 382 additions and 386 deletions
|
@ -1,50 +1,13 @@
|
||||||
#ifndef _memorymanip__hpp__included__
|
#ifndef _memorymanip__hpp__included__
|
||||||
#define _memorymanip__hpp__included__
|
#define _memorymanip__hpp__included__
|
||||||
|
|
||||||
|
#include "interface/core.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Information about region of memory
|
|
||||||
*
|
|
||||||
* This structure contains information about memory region.
|
|
||||||
*/
|
|
||||||
struct memory_region
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* \brief Name of region.
|
|
||||||
*
|
|
||||||
* This is name of region, mainly for debugging and showing to the user.
|
|
||||||
*/
|
|
||||||
std::string region_name;
|
|
||||||
/**
|
|
||||||
* \brief Base address of region.
|
|
||||||
*/
|
|
||||||
uint32_t baseaddr;
|
|
||||||
/**
|
|
||||||
* \brief Size of region in bytes.
|
|
||||||
*/
|
|
||||||
uint32_t size;
|
|
||||||
/**
|
|
||||||
* \brief Last valid address in this region.
|
|
||||||
*/
|
|
||||||
uint32_t lastaddr;
|
|
||||||
/**
|
|
||||||
* \brief True for ROM, false for RAM.
|
|
||||||
*/
|
|
||||||
bool readonly;
|
|
||||||
/**
|
|
||||||
* \brief Endianess of the region.
|
|
||||||
*
|
|
||||||
* If true, region uses host endian.
|
|
||||||
* If false, region uses SNES (big) endian.
|
|
||||||
*/
|
|
||||||
bool native_endian;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Refresh cart memory mappings
|
* \brief Refresh cart memory mappings
|
||||||
*
|
*
|
||||||
|
@ -62,7 +25,7 @@ void refresh_cart_mappings() throw(std::bad_alloc);
|
||||||
* \return All regions
|
* \return All regions
|
||||||
* \throws std::bad_alloc Not enough memory.
|
* \throws std::bad_alloc Not enough memory.
|
||||||
*/
|
*/
|
||||||
std::vector<struct memory_region> get_regions() throw(std::bad_alloc);
|
std::vector<vma_structure*> get_regions() throw(std::bad_alloc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Read byte from memory
|
* \brief Read byte from memory
|
||||||
|
@ -72,7 +35,7 @@ std::vector<struct memory_region> get_regions() throw(std::bad_alloc);
|
||||||
* \param addr The address to read.
|
* \param addr The address to read.
|
||||||
* \return The byte read.
|
* \return The byte read.
|
||||||
*/
|
*/
|
||||||
uint8_t memory_read_byte(uint32_t addr) throw();
|
uint8_t memory_read_byte(uint64_t addr) throw();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Read word from memory
|
* \brief Read word from memory
|
||||||
|
@ -82,7 +45,7 @@ uint8_t memory_read_byte(uint32_t addr) throw();
|
||||||
* \param addr The address to read.
|
* \param addr The address to read.
|
||||||
* \return The word read.
|
* \return The word read.
|
||||||
*/
|
*/
|
||||||
uint16_t memory_read_word(uint32_t addr) throw();
|
uint16_t memory_read_word(uint64_t addr) throw();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Read dword from memory
|
* \brief Read dword from memory
|
||||||
|
@ -92,7 +55,7 @@ uint16_t memory_read_word(uint32_t addr) throw();
|
||||||
* \param addr The address to read.
|
* \param addr The address to read.
|
||||||
* \return The dword read.
|
* \return The dword read.
|
||||||
*/
|
*/
|
||||||
uint32_t memory_read_dword(uint32_t addr) throw();
|
uint32_t memory_read_dword(uint64_t addr) throw();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Read qword from memory
|
* \brief Read qword from memory
|
||||||
|
@ -102,7 +65,7 @@ uint32_t memory_read_dword(uint32_t addr) throw();
|
||||||
* \param addr The address to read.
|
* \param addr The address to read.
|
||||||
* \return The qword read.
|
* \return The qword read.
|
||||||
*/
|
*/
|
||||||
uint64_t memory_read_qword(uint32_t addr) throw();
|
uint64_t memory_read_qword(uint64_t addr) throw();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Write byte to memory
|
* \brief Write byte to memory
|
||||||
|
@ -113,7 +76,7 @@ uint64_t memory_read_qword(uint32_t addr) throw();
|
||||||
* \param data The value to write.
|
* \param data The value to write.
|
||||||
* \return true if the write succeeded.
|
* \return true if the write succeeded.
|
||||||
*/
|
*/
|
||||||
bool memory_write_byte(uint32_t addr, uint8_t data) throw();
|
bool memory_write_byte(uint64_t addr, uint8_t data) throw();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Write word to memory
|
* \brief Write word to memory
|
||||||
|
@ -124,7 +87,7 @@ bool memory_write_byte(uint32_t addr, uint8_t data) throw();
|
||||||
* \param data The value to write.
|
* \param data The value to write.
|
||||||
* \return true if the write succeeded.
|
* \return true if the write succeeded.
|
||||||
*/
|
*/
|
||||||
bool memory_write_word(uint32_t addr, uint16_t data) throw();
|
bool memory_write_word(uint64_t addr, uint16_t data) throw();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Write dword to memory
|
* \brief Write dword to memory
|
||||||
|
@ -135,7 +98,7 @@ bool memory_write_word(uint32_t addr, uint16_t data) throw();
|
||||||
* \param data The value to write.
|
* \param data The value to write.
|
||||||
* \return true if the write succeeded.
|
* \return true if the write succeeded.
|
||||||
*/
|
*/
|
||||||
bool memory_write_dword(uint32_t addr, uint32_t data) throw();
|
bool memory_write_dword(uint64_t addr, uint32_t data) throw();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Write qword to memory
|
* \brief Write qword to memory
|
||||||
|
@ -146,7 +109,7 @@ bool memory_write_dword(uint32_t addr, uint32_t data) throw();
|
||||||
* \param data The value to write.
|
* \param data The value to write.
|
||||||
* \return true if the write succeeded.
|
* \return true if the write succeeded.
|
||||||
*/
|
*/
|
||||||
bool memory_write_qword(uint32_t addr, uint64_t data) throw();
|
bool memory_write_qword(uint64_t addr, uint64_t data) throw();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Memory search context
|
* \brief Memory search context
|
||||||
|
@ -412,7 +375,7 @@ public:
|
||||||
*
|
*
|
||||||
* \return The number of candidates
|
* \return The number of candidates
|
||||||
*/
|
*/
|
||||||
uint32_t get_candidate_count() throw();
|
uint64_t get_candidate_count() throw();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get List of all candidate addresses
|
* \brief Get List of all candidate addresses
|
||||||
|
@ -422,11 +385,11 @@ public:
|
||||||
* \return Candidate address list
|
* \return Candidate address list
|
||||||
* \throws std::bad_alloc Not enough memory.
|
* \throws std::bad_alloc Not enough memory.
|
||||||
*/
|
*/
|
||||||
std::list<uint32_t> get_candidates() throw(std::bad_alloc);
|
std::list<uint64_t> get_candidates() throw(std::bad_alloc);
|
||||||
private:
|
private:
|
||||||
std::vector<uint8_t> previous_content;
|
std::vector<uint8_t> previous_content;
|
||||||
std::vector<uint64_t> still_in;
|
std::vector<uint64_t> still_in;
|
||||||
uint32_t candidates;
|
uint64_t candidates;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,14 +12,43 @@ void emucore_basic_init();
|
||||||
|
|
||||||
struct sram_slot_structure
|
struct sram_slot_structure
|
||||||
{
|
{
|
||||||
|
virtual ~sram_slot_structure();
|
||||||
virtual std::string get_name() = 0;
|
virtual std::string get_name() = 0;
|
||||||
virtual void copy_to_core(const std::vector<char>& content) = 0;
|
virtual void copy_to_core(const std::vector<char>& content) = 0;
|
||||||
virtual void copy_from_core(std::vector<char>& content) = 0;
|
virtual void copy_from_core(std::vector<char>& content) = 0;
|
||||||
virtual size_t get_size() = 0; //0 if variable size.
|
virtual size_t get_size() = 0; //0 if variable size.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct vma_structure
|
||||||
|
{
|
||||||
|
enum endian
|
||||||
|
{
|
||||||
|
E_LITTLE = -1,
|
||||||
|
E_HOST = 0,
|
||||||
|
E_BIG = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
vma_structure(const std::string& _name, uint64_t _base, uint64_t _size, endian _rendian, bool _readonly);
|
||||||
|
virtual ~vma_structure();
|
||||||
|
std::string get_name() { return name; }
|
||||||
|
uint64_t get_base() { return base; }
|
||||||
|
uint64_t get_size() { return size; }
|
||||||
|
bool is_readonly() { return readonly; }
|
||||||
|
endian get_endian() { return rendian; }
|
||||||
|
virtual void copy_from_core(uint64_t start, char* buffer, uint64_t size) = 0;
|
||||||
|
virtual void copy_to_core(uint64_t start, const char* buffer, uint64_t size) = 0;
|
||||||
|
protected:
|
||||||
|
std::string name;
|
||||||
|
uint64_t base;
|
||||||
|
uint64_t size;
|
||||||
|
bool readonly;
|
||||||
|
endian rendian;
|
||||||
|
};
|
||||||
|
|
||||||
size_t emucore_sram_slots();
|
size_t emucore_sram_slots();
|
||||||
struct sram_slot_structure* emucore_sram_slot(size_t index);
|
struct sram_slot_structure* emucore_sram_slot(size_t index);
|
||||||
|
size_t emucore_vma_slots();
|
||||||
|
struct vma_structure* emucore_vma_slot(size_t index);
|
||||||
void emucore_refresh_cart();
|
void emucore_refresh_cart();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "core/memorymanip.hpp"
|
#include "core/memorymanip.hpp"
|
||||||
#include "core/misc.hpp"
|
#include "core/misc.hpp"
|
||||||
#include "core/rom.hpp"
|
#include "core/rom.hpp"
|
||||||
|
#include "interface/core.hpp"
|
||||||
#include "library/string.hpp"
|
#include "library/string.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -12,334 +13,174 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
/*
|
|
||||||
typedef uint8_t uint8;
|
|
||||||
typedef uint16_t uint16;
|
|
||||||
typedef uint32_t uint32;
|
|
||||||
typedef int8_t int8;
|
|
||||||
typedef int16_t int16;
|
|
||||||
typedef int32_t int32;
|
|
||||||
#include <nall/platform.hpp>
|
|
||||||
#include <nall/endian.hpp>
|
|
||||||
#include <nall/varint.hpp>
|
|
||||||
#include <nall/bit.hpp>
|
|
||||||
#include <nall/serializer.hpp>
|
|
||||||
#include <nall/property.hpp>
|
|
||||||
using namespace nall;
|
|
||||||
using namespace SNES;
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
struct translated_address
|
struct translated_address
|
||||||
{
|
{
|
||||||
uint32_t rel_addr;
|
uint64_t rel_addr; //Address relative to start of VMA.
|
||||||
uint32_t raw_addr;
|
uint64_t raw_addr; //Raw address.
|
||||||
uint8_t* memory;
|
uint64_t mem_size; //Memory size.
|
||||||
uint32_t memory_size;
|
vma_structure* vma; //VMA referred to.
|
||||||
bool not_writable;
|
bool read_only; //RO flag.
|
||||||
bool native_endian;
|
bool native_endian; //Is in native endian.
|
||||||
};
|
};
|
||||||
|
|
||||||
struct region
|
std::vector<vma_structure*> memory_regions;
|
||||||
{
|
uint64_t linear_ram_size = 0;
|
||||||
std::string name;
|
|
||||||
uint32_t base;
|
|
||||||
uint32_t size;
|
|
||||||
uint8_t* memory;
|
|
||||||
bool not_writable;
|
|
||||||
bool native_endian;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<region> memory_regions;
|
|
||||||
uint32_t linear_ram_size = 0;
|
|
||||||
bool system_little_endian = true;
|
bool system_little_endian = true;
|
||||||
|
|
||||||
struct translated_address translate_address(uint32_t rawaddr) throw()
|
struct translated_address translate_address(uint64_t rawaddr) throw()
|
||||||
{
|
{
|
||||||
struct translated_address t;
|
struct translated_address t;
|
||||||
t.rel_addr = 0;
|
t.rel_addr = 0;
|
||||||
t.raw_addr = 0;
|
t.raw_addr = 0;
|
||||||
t.memory = NULL;
|
t.mem_size = 0;
|
||||||
t.memory_size = 0;
|
t.vma = NULL;
|
||||||
t.not_writable = true;
|
t.read_only = true;
|
||||||
|
t.native_endian = true;
|
||||||
for(auto i : memory_regions) {
|
for(auto i : memory_regions) {
|
||||||
if(i.base > rawaddr || i.base + i.size <= rawaddr)
|
if(i->get_base() > rawaddr || i->get_base() + i->get_size() <= rawaddr)
|
||||||
continue;
|
continue;
|
||||||
t.rel_addr = rawaddr - i.base;
|
t.rel_addr = rawaddr - i->get_base();
|
||||||
t.raw_addr = rawaddr;
|
t.raw_addr = rawaddr;
|
||||||
t.memory = i.memory;
|
t.vma = i;
|
||||||
t.memory_size = i.size;
|
t.mem_size = i->get_size();
|
||||||
t.not_writable = i.not_writable;
|
t.read_only = i->is_readonly();
|
||||||
t.native_endian = i.native_endian;
|
t.native_endian = (!system_little_endian && i->get_endian() == vma_structure::E_BIG) ||
|
||||||
|
(system_little_endian && i->get_endian() == vma_structure::E_LITTLE) ||
|
||||||
|
i->get_endian() == vma_structure::E_HOST;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct translated_address translate_address_linear_ram(uint32_t ramlinaddr) throw()
|
struct translated_address translate_address_linear_ram(uint64_t ramlinaddr) throw()
|
||||||
{
|
{
|
||||||
struct translated_address t;
|
struct translated_address t;
|
||||||
t.rel_addr = 0;
|
t.rel_addr = 0;
|
||||||
t.raw_addr = 0;
|
t.raw_addr = 0;
|
||||||
t.memory = NULL;
|
t.mem_size = 0;
|
||||||
t.memory_size = 0;
|
t.vma = NULL;
|
||||||
t.not_writable = true;
|
t.read_only = true;
|
||||||
|
t.native_endian = true;
|
||||||
for(auto i : memory_regions) {
|
for(auto i : memory_regions) {
|
||||||
if(i.not_writable)
|
if(i->is_readonly())
|
||||||
continue;
|
continue;
|
||||||
if(ramlinaddr >= i.size) {
|
if(ramlinaddr >= i->get_size()) {
|
||||||
ramlinaddr -= i.size;
|
ramlinaddr -= i->get_size();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
t.rel_addr = ramlinaddr;
|
t.rel_addr = ramlinaddr;
|
||||||
t.raw_addr = i.base + ramlinaddr;
|
t.raw_addr = i->get_base() + ramlinaddr;
|
||||||
t.memory = i.memory;
|
t.vma = i;
|
||||||
t.memory_size = i.size;
|
t.mem_size = i->get_size();
|
||||||
t.not_writable = i.not_writable;
|
t.read_only = i->is_readonly();
|
||||||
t.native_endian = i.native_endian;
|
t.native_endian = (!system_little_endian && i->get_endian() == vma_structure::E_BIG) ||
|
||||||
|
(system_little_endian && i->get_endian() == vma_structure::E_LITTLE) ||
|
||||||
|
i->get_endian() == vma_structure::E_HOST;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t get_linear_ram_size() throw()
|
uint64_t get_linear_ram_size() throw()
|
||||||
{
|
{
|
||||||
return linear_ram_size;
|
return linear_ram_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t create_region(const std::string& name, uint32_t base, uint8_t* memory, uint32_t size, bool readonly,
|
void copy_regions_from_core()
|
||||||
bool native_endian = false) throw(std::bad_alloc)
|
|
||||||
{
|
{
|
||||||
if(size == 0)
|
uint64_t new_linsize = 0;
|
||||||
return base;
|
std::vector<vma_structure*> new_memory_regions;
|
||||||
struct region r;
|
for(size_t i = 0; i < emucore_vma_slots(); i++) {
|
||||||
r.name = name;
|
vma_structure* j = emucore_vma_slot(i);
|
||||||
r.base = base;
|
new_memory_regions.push_back(j);
|
||||||
r.memory = memory;
|
if(!j->is_readonly())
|
||||||
r.size = size;
|
new_linsize += j->get_size();
|
||||||
r.not_writable = readonly;
|
}
|
||||||
r.native_endian = native_endian;
|
std::swap(memory_regions, new_memory_regions);
|
||||||
if(!readonly)
|
linear_ram_size = new_linsize;
|
||||||
linear_ram_size += size;
|
|
||||||
memory_regions.push_back(r);
|
|
||||||
return base + size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t create_region(const std::string& name, uint32_t base, SNES::MappedRAM& memory, bool readonly,
|
template<typename T> T endian_convert(T x) throw();
|
||||||
bool native_endian = false) throw(std::bad_alloc)
|
|
||||||
{
|
|
||||||
return create_region(name, base, memory.data(), memory.size(), readonly, native_endian);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t native_littleendian_convert(uint16_t x) throw()
|
template<> uint8_t endian_convert(uint8_t x) throw()
|
||||||
{
|
{
|
||||||
if(!system_little_endian)
|
|
||||||
return (((x >> 8) & 0xFF) | ((x << 8) & 0xFF00));
|
|
||||||
else
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t native_littleendian_convert(uint32_t x) throw()
|
template<> uint16_t endian_convert(uint16_t x) throw()
|
||||||
|
{
|
||||||
|
return (((x >> 8) & 0xFF) | ((x << 8) & 0xFF00));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> uint32_t endian_convert(uint32_t x) throw()
|
||||||
{
|
{
|
||||||
if(!system_little_endian)
|
|
||||||
return (((x >> 24) & 0xFF) | ((x >> 8) & 0xFF00) |
|
return (((x >> 24) & 0xFF) | ((x >> 8) & 0xFF00) |
|
||||||
((x << 8) & 0xFF0000) | ((x << 24) & 0xFF000000));
|
((x << 8) & 0xFF0000) | ((x << 24) & 0xFF000000));
|
||||||
else
|
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t native_littleendian_convert(uint64_t x) throw()
|
template<> uint64_t endian_convert(uint64_t x) throw()
|
||||||
{
|
{
|
||||||
if(!system_little_endian)
|
|
||||||
return (((x >> 56) & 0xFF) | ((x >> 40) & 0xFF00) |
|
return (((x >> 56) & 0xFF) | ((x >> 40) & 0xFF00) |
|
||||||
((x >> 24) & 0xFF0000) | ((x >> 8) & 0xFF000000) |
|
((x >> 24) & 0xFF0000) | ((x >> 8) & 0xFF000000) |
|
||||||
((x << 8) & 0xFF00000000ULL) | ((x << 24) & 0xFF0000000000ULL) |
|
((x << 8) & 0xFF00000000ULL) | ((x << 24) & 0xFF0000000000ULL) |
|
||||||
((x << 40) & 0xFF000000000000ULL) | ((x << 56) & 0xFF00000000000000ULL));
|
((x << 40) & 0xFF000000000000ULL) | ((x << 56) & 0xFF00000000000000ULL));
|
||||||
else
|
}
|
||||||
return x;
|
|
||||||
|
template<> int8_t endian_convert(int8_t x) throw() { return endian_convert(static_cast<uint8_t>(x)); }
|
||||||
|
template<> int16_t endian_convert(int16_t x) throw() { return endian_convert(static_cast<uint16_t>(x)); }
|
||||||
|
template<> int32_t endian_convert(int32_t x) throw() { return endian_convert(static_cast<uint32_t>(x)); }
|
||||||
|
template<> int64_t endian_convert(int64_t x) throw() { return endian_convert(static_cast<uint64_t>(x)); }
|
||||||
|
|
||||||
|
template<typename T> T memory_read(uint64_t addr) throw()
|
||||||
|
{
|
||||||
|
struct translated_address laddr = translate_address(addr);
|
||||||
|
T value = 0;
|
||||||
|
laddr.vma->copy_from_core(laddr.rel_addr, reinterpret_cast<char*>(&value), sizeof(T));
|
||||||
|
if(!laddr.native_endian)
|
||||||
|
value = endian_convert(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Byte write to address (false if failed).
|
||||||
|
template<typename T> bool memory_write(uint64_t addr, T data) throw()
|
||||||
|
{
|
||||||
|
struct translated_address laddr = translate_address(addr);
|
||||||
|
if(laddr.rel_addr > laddr.mem_size - sizeof(T) || laddr.read_only)
|
||||||
|
return false;
|
||||||
|
if(!laddr.native_endian)
|
||||||
|
data = endian_convert(data);
|
||||||
|
laddr.vma->copy_to_core(laddr.rel_addr, reinterpret_cast<char*>(&data), sizeof(T));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void refresh_cart_mappings() throw(std::bad_alloc)
|
void refresh_cart_mappings() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
linear_ram_size = 0;
|
uint16_t x = 258;
|
||||||
memory_regions.clear();
|
system_little_endian = (*reinterpret_cast<char*>(&x) == 2);
|
||||||
if(get_current_rom_info().first == ROMTYPE_NONE)
|
emucore_refresh_cart();
|
||||||
return;
|
copy_regions_from_core();
|
||||||
create_region("WRAM", 0x007E0000, SNES::cpu.wram, 131072, false);
|
|
||||||
create_region("APURAM", 0x00000000, SNES::smp.apuram, 65536, false);
|
|
||||||
create_region("VRAM", 0x00010000, SNES::ppu.vram, 65536, false);
|
|
||||||
create_region("OAM", 0x00020000, SNES::ppu.oam, 544, false);
|
|
||||||
create_region("CGRAM", 0x00021000, SNES::ppu.cgram, 512, false);
|
|
||||||
if(SNES::cartridge.has_srtc()) create_region("RTC", 0x00022000, SNES::srtc.rtc, 20, false);
|
|
||||||
if(SNES::cartridge.has_spc7110rtc()) create_region("RTC", 0x00022000, SNES::spc7110.rtc, 20, false);
|
|
||||||
if(SNES::cartridge.has_necdsp()) {
|
|
||||||
create_region("DSPRAM", 0x00023000, reinterpret_cast<uint8_t*>(SNES::necdsp.dataRAM), 4096, false,
|
|
||||||
true);
|
|
||||||
create_region("DSPPROM", 0xF0000000, reinterpret_cast<uint8_t*>(SNES::necdsp.programROM), 65536, true,
|
|
||||||
true);
|
|
||||||
create_region("DSPDROM", 0xF0010000, reinterpret_cast<uint8_t*>(SNES::necdsp.dataROM), 4096, true,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
create_region("SRAM", 0x10000000, SNES::cartridge.ram, false);
|
|
||||||
create_region("ROM", 0x80000000, SNES::cartridge.rom, true);
|
|
||||||
switch(get_current_rom_info().first) {
|
|
||||||
case ROMTYPE_BSX:
|
|
||||||
case ROMTYPE_BSXSLOTTED:
|
|
||||||
create_region("BSXFLASH", 0x90000000, SNES::bsxflash.memory, true);
|
|
||||||
create_region("BSX_RAM", 0x20000000, SNES::bsxcartridge.sram, false);
|
|
||||||
create_region("BSX_PRAM", 0x30000000, SNES::bsxcartridge.psram, false);
|
|
||||||
break;
|
|
||||||
case ROMTYPE_SUFAMITURBO:
|
|
||||||
create_region("SLOTA_ROM", 0x90000000, SNES::sufamiturbo.slotA.rom, true);
|
|
||||||
create_region("SLOTB_ROM", 0xA0000000, SNES::sufamiturbo.slotB.rom, true);
|
|
||||||
create_region("SLOTA_RAM", 0x20000000, SNES::sufamiturbo.slotA.ram, false);
|
|
||||||
create_region("SLOTB_RAM", 0x30000000, SNES::sufamiturbo.slotB.ram, false);
|
|
||||||
break;
|
|
||||||
case ROMTYPE_SGB:
|
|
||||||
create_region("GBROM", 0x90000000, GameBoy::cartridge.romdata, GameBoy::cartridge.romsize, true);
|
|
||||||
create_region("GBRAM", 0x20000000, GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize, false);
|
|
||||||
break;
|
|
||||||
case ROMTYPE_SNES:
|
|
||||||
case ROMTYPE_NONE:
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<struct memory_region> get_regions() throw(std::bad_alloc)
|
std::vector<vma_structure*> get_regions() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
std::vector<struct memory_region> out;
|
std::vector<vma_structure*> out;
|
||||||
for(auto i : memory_regions) {
|
for(auto i : memory_regions)
|
||||||
struct memory_region r;
|
out.push_back(i);
|
||||||
r.region_name = i.name;
|
|
||||||
r.baseaddr = i.base;
|
|
||||||
r.size = i.size;
|
|
||||||
r.lastaddr = i.base + i.size - 1;
|
|
||||||
r.readonly = i.not_writable;
|
|
||||||
r.native_endian = i.native_endian;
|
|
||||||
out.push_back(r);
|
|
||||||
}
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t memory_read_byte(uint32_t addr) throw()
|
uint8_t memory_read_byte(uint64_t addr) throw() { return memory_read<uint8_t>(addr); }
|
||||||
{
|
uint16_t memory_read_word(uint64_t addr) throw() { return memory_read<uint16_t>(addr); }
|
||||||
struct translated_address laddr = translate_address(addr);
|
uint32_t memory_read_dword(uint64_t addr) throw() { return memory_read<uint32_t>(addr); }
|
||||||
uint8_t value = 0;
|
uint64_t memory_read_qword(uint64_t addr) throw() { return memory_read<uint64_t>(addr); }
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
bool memory_write_byte(uint64_t addr, uint8_t data) throw() { return memory_write(addr, data); }
|
||||||
value |= laddr.memory[laddr.rel_addr++];
|
bool memory_write_word(uint64_t addr, uint16_t data) throw() { return memory_write(addr, data); }
|
||||||
return value;
|
bool memory_write_dword(uint64_t addr, uint32_t data) throw() { return memory_write(addr, data); }
|
||||||
}
|
bool memory_write_qword(uint64_t addr, uint64_t data) throw() { return memory_write(addr, data); }
|
||||||
|
|
||||||
uint16_t memory_read_word(uint32_t addr) throw()
|
|
||||||
{
|
|
||||||
struct translated_address laddr = translate_address(addr);
|
|
||||||
uint16_t value = 0;
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint16_t>(laddr.memory[laddr.rel_addr++]));
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint16_t>(laddr.memory[laddr.rel_addr++]) << 8);
|
|
||||||
if(laddr.native_endian)
|
|
||||||
value = native_littleendian_convert(value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t memory_read_dword(uint32_t addr) throw()
|
|
||||||
{
|
|
||||||
struct translated_address laddr = translate_address(addr);
|
|
||||||
uint32_t value = 0;
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint32_t>(laddr.memory[laddr.rel_addr++]));
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint32_t>(laddr.memory[laddr.rel_addr++]) << 8);
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint32_t>(laddr.memory[laddr.rel_addr++]) << 16);
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint32_t>(laddr.memory[laddr.rel_addr++]) << 24);
|
|
||||||
if(laddr.native_endian)
|
|
||||||
value = native_littleendian_convert(value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t memory_read_qword(uint32_t addr) throw()
|
|
||||||
{
|
|
||||||
struct translated_address laddr = translate_address(addr);
|
|
||||||
uint64_t value = 0;
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint64_t>(laddr.memory[laddr.rel_addr++]));
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint64_t>(laddr.memory[laddr.rel_addr++]) << 8);
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint64_t>(laddr.memory[laddr.rel_addr++]) << 16);
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint64_t>(laddr.memory[laddr.rel_addr++]) << 24);
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint64_t>(laddr.memory[laddr.rel_addr++]) << 32);
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint64_t>(laddr.memory[laddr.rel_addr++]) << 40);
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint64_t>(laddr.memory[laddr.rel_addr++]) << 48);
|
|
||||||
if(laddr.rel_addr < laddr.memory_size)
|
|
||||||
value |= (static_cast<uint64_t>(laddr.memory[laddr.rel_addr++]) << 56);
|
|
||||||
if(laddr.native_endian)
|
|
||||||
value = native_littleendian_convert(value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Byte write to address (false if failed).
|
|
||||||
bool memory_write_byte(uint32_t addr, uint8_t data) throw()
|
|
||||||
{
|
|
||||||
struct translated_address laddr = translate_address(addr);
|
|
||||||
if(laddr.rel_addr >= laddr.memory_size || laddr.not_writable)
|
|
||||||
return false;
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool memory_write_word(uint32_t addr, uint16_t data) throw()
|
|
||||||
{
|
|
||||||
struct translated_address laddr = translate_address(addr);
|
|
||||||
if(laddr.native_endian)
|
|
||||||
data = native_littleendian_convert(data);
|
|
||||||
if(laddr.rel_addr >= laddr.memory_size - 1 || laddr.not_writable)
|
|
||||||
return false;
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data);
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data >> 8);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool memory_write_dword(uint32_t addr, uint32_t data) throw()
|
|
||||||
{
|
|
||||||
struct translated_address laddr = translate_address(addr);
|
|
||||||
if(laddr.native_endian)
|
|
||||||
data = native_littleendian_convert(data);
|
|
||||||
if(laddr.rel_addr >= laddr.memory_size - 3 || laddr.not_writable)
|
|
||||||
return false;
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data);
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data >> 8);
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data >> 16);
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data >> 24);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool memory_write_qword(uint32_t addr, uint64_t data) throw()
|
|
||||||
{
|
|
||||||
struct translated_address laddr = translate_address(addr);
|
|
||||||
if(laddr.native_endian)
|
|
||||||
data = native_littleendian_convert(data);
|
|
||||||
if(laddr.rel_addr >= laddr.memory_size - 7 || laddr.not_writable)
|
|
||||||
return false;
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data);
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data >> 8);
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data >> 16);
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data >> 24);
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data >> 32);
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data >> 40);
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data >> 48);
|
|
||||||
laddr.memory[laddr.rel_addr++] = static_cast<uint8_t>(data >> 56);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
memorysearch::memorysearch() throw(std::bad_alloc)
|
memorysearch::memorysearch() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
@ -348,18 +189,18 @@ memorysearch::memorysearch() throw(std::bad_alloc)
|
||||||
|
|
||||||
void memorysearch::reset() throw(std::bad_alloc)
|
void memorysearch::reset() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
uint32_t linearram = get_linear_ram_size();
|
uint64_t linearram = get_linear_ram_size();
|
||||||
previous_content.resize(linearram);
|
previous_content.resize(linearram);
|
||||||
still_in.resize((linearram + 63) / 64);
|
still_in.resize((linearram + 63) / 64);
|
||||||
for(uint32_t i = 0; i < linearram / 64; i++)
|
for(uint64_t i = 0; i < linearram / 64; i++)
|
||||||
still_in[i] = 0xFFFFFFFFFFFFFFFFULL;
|
still_in[i] = 0xFFFFFFFFFFFFFFFFULL;
|
||||||
if(linearram % 64)
|
if(linearram % 64)
|
||||||
still_in[linearram / 64] = (1ULL << (linearram % 64)) - 1;
|
still_in[linearram / 64] = (1ULL << (linearram % 64)) - 1;
|
||||||
uint32_t addr = 0;
|
uint64_t addr = 0;
|
||||||
while(addr < linearram) {
|
while(addr < linearram) {
|
||||||
struct translated_address t = translate_address_linear_ram(addr);
|
struct translated_address t = translate_address_linear_ram(addr);
|
||||||
memcpy(&previous_content[addr], t.memory, t.memory_size);
|
t.vma->copy_from_core(0, reinterpret_cast<char*>(&previous_content[addr]), t.mem_size);
|
||||||
addr += t.memory_size;
|
addr += t.mem_size;
|
||||||
}
|
}
|
||||||
candidates = linearram;
|
candidates = linearram;
|
||||||
}
|
}
|
||||||
|
@ -594,19 +435,15 @@ struct search_value_helper
|
||||||
*
|
*
|
||||||
* This function is search()-compatible condition function calling the underlying condition.
|
* This function is search()-compatible condition function calling the underlying condition.
|
||||||
*/
|
*/
|
||||||
bool operator()(const uint8_t* newv, const uint8_t* oldv, uint32_t left, bool nativeendian) const throw()
|
bool operator()(const uint8_t* newv, const uint8_t* oldv, uint64_t left, bool nativeendian) const throw()
|
||||||
{
|
{
|
||||||
if(left < sizeof(value_type))
|
if(left < sizeof(value_type))
|
||||||
return false;
|
return false;
|
||||||
value_type v1 = 0;
|
value_type v1 = *reinterpret_cast<const value_type*>(oldv);
|
||||||
value_type v2 = 0;
|
value_type v2 = *reinterpret_cast<const value_type*>(newv);
|
||||||
if(nativeendian) {
|
if(!nativeendian) {
|
||||||
v1 = *reinterpret_cast<const value_type*>(oldv);
|
v1 = endian_convert<value_type>(v1);
|
||||||
v2 = *reinterpret_cast<const value_type*>(newv);
|
v2 = endian_convert<value_type>(v2);
|
||||||
} else
|
|
||||||
for(size_t i = 0; i < sizeof(value_type); i++) {
|
|
||||||
v1 |= static_cast<value_type>(oldv[i]) << (8 * i);
|
|
||||||
v2 |= static_cast<value_type>(newv[i]) << (8 * i);
|
|
||||||
}
|
}
|
||||||
return val(v1, v2);
|
return val(v1, v2);
|
||||||
}
|
}
|
||||||
|
@ -617,42 +454,70 @@ struct search_value_helper
|
||||||
const T& val;
|
const T& val;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BUFFER_LOWATER_MARK 16
|
||||||
|
#define BUFFER_HIWATER_MARK 4096
|
||||||
|
|
||||||
template<class T> void memorysearch::search(const T& obj) throw()
|
template<class T> void memorysearch::search(const T& obj) throw()
|
||||||
{
|
{
|
||||||
search_value_helper<T> helper(obj);
|
search_value_helper<T> helper(obj);
|
||||||
struct translated_address t = translate_address_linear_ram(0);
|
struct translated_address t = translate_address_linear_ram(0);
|
||||||
uint32_t switch_at = t.memory_size;
|
uint64_t switch_at = t.mem_size;
|
||||||
uint32_t base = 0;
|
uint64_t base = 0;
|
||||||
uint32_t size = previous_content.size();
|
uint64_t size = previous_content.size();
|
||||||
for(uint32_t i = 0; i < size; i++) {
|
uint8_t buffer[BUFFER_HIWATER_MARK];
|
||||||
|
size_t bufferfill = 0;
|
||||||
|
size_t bufferused = 0;
|
||||||
|
for(uint64_t i = 0; i < size; i++) {
|
||||||
if(still_in[i / 64] == 0) {
|
if(still_in[i / 64] == 0) {
|
||||||
|
uint64_t old_i = i;
|
||||||
i = (i + 64) >> 6 << 6;
|
i = (i + 64) >> 6 << 6;
|
||||||
|
size_t delta_i = i - old_i;
|
||||||
|
bufferused += delta_i;
|
||||||
|
if(bufferused > bufferfill)
|
||||||
|
bufferused = bufferfill = 0;
|
||||||
i--;
|
i--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//t.memory_size == 0 can happen if cart changes.
|
//t.mem_size == 0 can happen if cart changes.
|
||||||
while(i >= switch_at && t.memory_size > 0) {
|
while(i >= switch_at && t.mem_size > 0) {
|
||||||
t = translate_address_linear_ram(switch_at);
|
t = translate_address_linear_ram(switch_at);
|
||||||
base = switch_at;
|
base = switch_at;
|
||||||
switch_at += t.memory_size;
|
switch_at += t.mem_size;
|
||||||
|
bufferfill = 0;
|
||||||
|
bufferused = 0;
|
||||||
}
|
}
|
||||||
if(t.memory_size == 0 || !helper(t.memory + i - base, &previous_content[i],
|
if(bufferfill - bufferused < BUFFER_LOWATER_MARK && i - bufferused + bufferfill < switch_at) {
|
||||||
t.memory_size - (i - base), t.native_endian)) {
|
//Right now the buffer covers the region from [i - bufferused, i - bufferused + bufferfill).
|
||||||
|
if(bufferused < bufferfill)
|
||||||
|
memmove(buffer, buffer + bufferused, bufferfill - bufferused);
|
||||||
|
bufferfill -= bufferused;
|
||||||
|
bufferused = 0;
|
||||||
|
//Right now the buffer covers the region from [i, i + bufferfill).
|
||||||
|
size_t csize = min(static_cast<uint64_t>(BUFFER_HIWATER_MARK), t.mem_size - (i - base)) -
|
||||||
|
bufferfill;
|
||||||
|
t.vma->copy_from_core(i - base + bufferfill, reinterpret_cast<char*>(buffer + bufferfill),
|
||||||
|
csize);
|
||||||
|
bufferfill += csize;
|
||||||
|
}
|
||||||
|
if(t.mem_size == 0 || !helper(buffer + bufferused, &previous_content[i], t.mem_size - (i - base),
|
||||||
|
t.native_endian)) {
|
||||||
if((still_in[i / 64] >> (i % 64)) & 1) {
|
if((still_in[i / 64] >> (i % 64)) & 1) {
|
||||||
still_in[i / 64] &= ~(1ULL << (i % 64));
|
still_in[i / 64] &= ~(1ULL << (i % 64));
|
||||||
candidates--;
|
candidates--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(t.mem_size > 0)
|
||||||
|
bufferused++;
|
||||||
}
|
}
|
||||||
t = translate_address_linear_ram(0);
|
t = translate_address_linear_ram(0);
|
||||||
base = 0;
|
base = 0;
|
||||||
size = previous_content.size();
|
size = previous_content.size();
|
||||||
while(base < size) {
|
while(base < size) {
|
||||||
size_t m = t.memory_size;
|
size_t m = t.mem_size;
|
||||||
if(m > (size - base))
|
if(m > (size - base))
|
||||||
m = size - base;
|
m = size - base;
|
||||||
memcpy(&previous_content[base], t.memory, m);
|
t.vma->copy_from_core(0, reinterpret_cast<char*>(&previous_content[base]), m);
|
||||||
base += t.memory_size;
|
base += t.mem_size;
|
||||||
t = translate_address_linear_ram(base);
|
t = translate_address_linear_ram(base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -715,36 +580,35 @@ void memorysearch::qword_ugt() throw() { search(search_gt<uint64_t>()); }
|
||||||
|
|
||||||
void memorysearch::update() throw() { search(search_update()); }
|
void memorysearch::update() throw() { search(search_update()); }
|
||||||
|
|
||||||
uint32_t memorysearch::get_candidate_count() throw()
|
uint64_t memorysearch::get_candidate_count() throw()
|
||||||
{
|
{
|
||||||
return candidates;
|
return candidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<uint32_t> memorysearch::get_candidates() throw(std::bad_alloc)
|
std::list<uint64_t> memorysearch::get_candidates() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
struct translated_address t = translate_address_linear_ram(0);
|
struct translated_address t = translate_address_linear_ram(0);
|
||||||
uint32_t switch_at = t.memory_size;
|
uint64_t switch_at = t.mem_size;
|
||||||
uint32_t base = 0;
|
uint64_t base = 0;
|
||||||
uint32_t rbase = t.raw_addr;
|
uint64_t rbase = t.raw_addr;
|
||||||
uint32_t size = previous_content.size();
|
uint64_t size = previous_content.size();
|
||||||
std::list<uint32_t> out;
|
std::list<uint64_t> out;
|
||||||
|
|
||||||
for(uint32_t i = 0; i < size; i++) {
|
for(uint64_t i = 0; i < size; i++) {
|
||||||
if(still_in[i / 64] == 0) {
|
if(still_in[i / 64] == 0) {
|
||||||
i = (i + 64) >> 6 << 6;
|
i = (i + 64) >> 6 << 6;
|
||||||
i--;
|
i--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
while(i >= switch_at && t.memory_size > 0) {
|
while(i >= switch_at && t.mem_size > 0) {
|
||||||
t = translate_address_linear_ram(switch_at);
|
t = translate_address_linear_ram(switch_at);
|
||||||
base = switch_at;
|
base = switch_at;
|
||||||
rbase = t.raw_addr - t.rel_addr;
|
rbase = t.raw_addr - t.rel_addr;
|
||||||
switch_at += t.memory_size;
|
switch_at += t.mem_size;
|
||||||
}
|
}
|
||||||
if((still_in[i / 64] >> (i % 64)) & 1)
|
if((still_in[i / 64] >> (i % 64)) & 1)
|
||||||
out.push_back(i - base + rbase);
|
out.push_back(i - base + rbase);
|
||||||
}
|
}
|
||||||
std::cout << "out=" << out.size() << " candidates=" << candidates << std::endl;
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -799,13 +663,13 @@ namespace
|
||||||
has_value = (secondword != "");
|
has_value = (secondword != "");
|
||||||
try {
|
try {
|
||||||
if(t = regex("0x(.+)", firstword)) {
|
if(t = regex("0x(.+)", firstword)) {
|
||||||
if(t[1].length() > 8)
|
if(t[1].length() > 16)
|
||||||
throw 42;
|
throw 42;
|
||||||
address = 0;
|
address = 0;
|
||||||
for(unsigned i = 0; i < t[1].length(); i++)
|
for(unsigned i = 0; i < t[1].length(); i++)
|
||||||
address = 16 * address + hex(t[1][i]);
|
address = 16 * address + hex(t[1][i]);
|
||||||
} else {
|
} else {
|
||||||
address = parse_value<uint32_t>(firstword);
|
address = parse_value<uint64_t>(firstword);
|
||||||
}
|
}
|
||||||
address_bad = false;
|
address_bad = false;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
@ -830,7 +694,7 @@ namespace
|
||||||
virtual void invoke2() throw(std::bad_alloc, std::runtime_error) = 0;
|
virtual void invoke2() throw(std::bad_alloc, std::runtime_error) = 0;
|
||||||
std::string firstword;
|
std::string firstword;
|
||||||
std::string secondword;
|
std::string secondword;
|
||||||
uint32_t address;
|
uint64_t address;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
bool has_tail;
|
bool has_tail;
|
||||||
bool address_bad;
|
bool address_bad;
|
||||||
|
@ -843,7 +707,7 @@ namespace
|
||||||
class read_command : public memorymanip_command
|
class read_command : public memorymanip_command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
read_command(const std::string& cmd, ret (*_rfn)(uint32_t addr)) throw(std::bad_alloc)
|
read_command(const std::string& cmd, ret (*_rfn)(uint64_t addr)) throw(std::bad_alloc)
|
||||||
: memorymanip_command(cmd)
|
: memorymanip_command(cmd)
|
||||||
{
|
{
|
||||||
rfn = _rfn;
|
rfn = _rfn;
|
||||||
|
@ -867,14 +731,14 @@ namespace
|
||||||
"Reads data from memory.\n";
|
"Reads data from memory.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
ret (*rfn)(uint32_t addr);
|
ret (*rfn)(uint64_t addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename arg, int64_t low, uint64_t high>
|
template<typename arg, int64_t low, uint64_t high>
|
||||||
class write_command : public memorymanip_command
|
class write_command : public memorymanip_command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
write_command(const std::string& cmd, bool (*_wfn)(uint32_t addr, arg a)) throw(std::bad_alloc)
|
write_command(const std::string& cmd, bool (*_wfn)(uint64_t addr, arg a)) throw(std::bad_alloc)
|
||||||
: memorymanip_command(cmd)
|
: memorymanip_command(cmd)
|
||||||
{
|
{
|
||||||
wfn = _wfn;
|
wfn = _wfn;
|
||||||
|
@ -895,7 +759,7 @@ namespace
|
||||||
return "Syntax: " + _command + " <address> <value>\n"
|
return "Syntax: " + _command + " <address> <value>\n"
|
||||||
"Writes data to memory.\n";
|
"Writes data to memory.\n";
|
||||||
}
|
}
|
||||||
bool (*wfn)(uint32_t addr, arg a);
|
bool (*wfn)(uint64_t addr, arg a);
|
||||||
};
|
};
|
||||||
|
|
||||||
class memorysearch_command : public memorymanip_command
|
class memorysearch_command : public memorymanip_command
|
||||||
|
@ -1026,7 +890,7 @@ namespace
|
||||||
auto c = isrch->get_candidates();
|
auto c = isrch->get_candidates();
|
||||||
for(auto ci : c) {
|
for(auto ci : c) {
|
||||||
std::ostringstream x;
|
std::ostringstream x;
|
||||||
x << "0x" << std::hex << std::setw(8) << std::setfill('0') << ci;
|
x << "0x" << std::hex << std::setw(16) << std::setfill('0') << ci;
|
||||||
messages << x.str() << std::endl;
|
messages << x.str() << std::endl;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -141,11 +141,18 @@ struct loaded_rom load_rom_from_commandline(std::vector<std::string> cmdline) th
|
||||||
|
|
||||||
void dump_region_map() throw(std::bad_alloc)
|
void dump_region_map() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
std::vector<struct memory_region> regions = get_regions();
|
std::vector<vma_structure*> regions = get_regions();
|
||||||
for(auto i : regions) {
|
for(auto i : regions) {
|
||||||
char buf[256];
|
char buf[256];
|
||||||
sprintf(buf, "Region: %08X-%08X %08X %s%c %s", i.baseaddr, i.lastaddr, i.size,
|
char echar;
|
||||||
i.readonly ? "R-" : "RW", i.native_endian ? 'N' : 'L', i.region_name.c_str());
|
if(i->get_endian() == vma_structure::E_LITTLE)
|
||||||
|
echar = 'L';
|
||||||
|
if(i->get_endian() == vma_structure::E_BIG)
|
||||||
|
echar = 'B';
|
||||||
|
if(i->get_endian() == vma_structure::E_HOST)
|
||||||
|
echar = 'N';
|
||||||
|
sprintf(buf, "Region: %016X-%016X %016X %s%c %s", i->get_base(), i->get_base() + i->get_size() - 1,
|
||||||
|
i->get_size(), i->is_readonly() ? "R-" : "RW", echar, i->get_name().c_str());
|
||||||
messages << buf << std::endl;
|
messages << buf << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "core/bsnes.hpp"
|
#include "core/bsnes.hpp"
|
||||||
|
#include <gameboy/gameboy.hpp>
|
||||||
#include "interface/core.hpp"
|
#include "interface/core.hpp"
|
||||||
|
#include "library/minmax.hpp"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,7 +116,42 @@ namespace
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bsnes_vma_slot : public vma_structure
|
||||||
|
{
|
||||||
|
bsnes_vma_slot(const std::string& _name, unsigned char* _memory, uint64_t _base, uint64_t _size,
|
||||||
|
endian _rendian, bool _readonly)
|
||||||
|
: vma_structure(_name, _base, _size, _rendian, _readonly)
|
||||||
|
{
|
||||||
|
memory = _memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_from_core(uint64_t start, char* buffer, uint64_t _size)
|
||||||
|
{
|
||||||
|
uint64_t inrange = _size;
|
||||||
|
if(start >= size)
|
||||||
|
inrange = 0;
|
||||||
|
inrange = min(inrange, size - start);
|
||||||
|
if(inrange)
|
||||||
|
memcpy(buffer, memory + start, inrange);
|
||||||
|
if(inrange < _size)
|
||||||
|
memset(buffer + inrange, 0, _size - inrange);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_to_core(uint64_t start, const char* buffer, uint64_t _size)
|
||||||
|
{
|
||||||
|
uint64_t inrange = _size;
|
||||||
|
if(start >= size)
|
||||||
|
inrange = 0;
|
||||||
|
inrange = min(inrange, size - start);
|
||||||
|
if(inrange && !readonly)
|
||||||
|
memcpy(memory + start, buffer, inrange);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
unsigned char* memory;
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<bsnes_sram_slot*> sram_slots;
|
std::vector<bsnes_sram_slot*> sram_slots;
|
||||||
|
std::vector<bsnes_vma_slot*> vma_slots;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t emucore_sram_slots()
|
size_t emucore_sram_slots()
|
||||||
|
@ -129,9 +166,22 @@ struct sram_slot_structure* emucore_sram_slot(size_t index)
|
||||||
return sram_slots[index];
|
return sram_slots[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t emucore_vma_slots()
|
||||||
|
{
|
||||||
|
return vma_slots.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct vma_structure* emucore_vma_slot(size_t index)
|
||||||
|
{
|
||||||
|
if(index >= vma_slots.size())
|
||||||
|
return NULL;
|
||||||
|
return vma_slots[index];
|
||||||
|
}
|
||||||
|
|
||||||
void emucore_refresh_cart()
|
void emucore_refresh_cart()
|
||||||
{
|
{
|
||||||
std::vector<bsnes_sram_slot*> new_sram_slots;
|
std::vector<bsnes_sram_slot*> new_sram_slots;
|
||||||
|
std::vector<bsnes_vma_slot*> new_vma_slots;
|
||||||
size_t slots = SNES::cartridge.nvram.size();
|
size_t slots = SNES::cartridge.nvram.size();
|
||||||
new_sram_slots.resize(slots);
|
new_sram_slots.resize(slots);
|
||||||
for(size_t i = 0; i < slots; i++)
|
for(size_t i = 0; i < slots; i++)
|
||||||
|
@ -142,13 +192,78 @@ void emucore_refresh_cart()
|
||||||
SNES::Cartridge::NonVolatileRAM& s = SNES::cartridge.nvram[i];
|
SNES::Cartridge::NonVolatileRAM& s = SNES::cartridge.nvram[i];
|
||||||
new_sram_slots[i] = new bsnes_sram_slot(s.id, s.slot, s.data, s.size);
|
new_sram_slots[i] = new bsnes_sram_slot(s.id, s.slot, s.data, s.size);
|
||||||
}
|
}
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("WRAM", SNES::cpu.wram, 0x007E0000, 131072,
|
||||||
|
vma_structure::E_LITTLE, false));
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("APURAM", SNES::smp.apuram, 0x00000000, 65536,
|
||||||
|
vma_structure::E_LITTLE, false));
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("VRAM", SNES::ppu.vram, 0x00010000, 65536,
|
||||||
|
vma_structure::E_LITTLE, false));
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("OAM", SNES::ppu.oam, 0x00020000, 544,
|
||||||
|
vma_structure::E_LITTLE, false));
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("CGRAM", SNES::ppu.cgram, 0x00021000, 512,
|
||||||
|
vma_structure::E_LITTLE, false));
|
||||||
|
if(SNES::cartridge.ram.size() > 0)
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("SRAM", SNES::cartridge.ram.data(), 0x10000000,
|
||||||
|
SNES::cartridge.ram.size(), vma_structure::E_LITTLE, false));
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("ROM", SNES::cartridge.rom.data(), 0x80000000,
|
||||||
|
SNES::cartridge.rom.size(), vma_structure::E_LITTLE, true));
|
||||||
|
if(SNES::cartridge.has_srtc())
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("RTC", SNES::srtc.rtc, 0x00022000, 20,
|
||||||
|
vma_structure::E_LITTLE, false));
|
||||||
|
if(SNES::cartridge.has_spc7110rtc())
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("RTC", SNES::spc7110.rtc, 0x00022000, 20,
|
||||||
|
vma_structure::E_LITTLE, false));
|
||||||
|
if(SNES::cartridge.has_necdsp()) {
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("DSPRAM",
|
||||||
|
reinterpret_cast<uint8_t*>(SNES::necdsp.dataRAM), 0x00023000, 4096,
|
||||||
|
vma_structure::E_HOST, false));
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("DSPPROM",
|
||||||
|
reinterpret_cast<uint8_t*>(SNES::necdsp.programROM), 0xF0000000, 65536,
|
||||||
|
vma_structure::E_HOST, true));
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("DSPDROMM",
|
||||||
|
reinterpret_cast<uint8_t*>(SNES::necdsp.dataROM), 0xF0010000, 4096,
|
||||||
|
vma_structure::E_HOST, true));
|
||||||
|
}
|
||||||
|
if(SNES::cartridge.mode() == SNES::Cartridge::Mode::Bsx ||
|
||||||
|
SNES::cartridge.mode() == SNES::Cartridge::Mode::BsxSlotted) {
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("BSXFLASH",
|
||||||
|
SNES::bsxflash.memory.data(), 0x90000000, SNES::bsxflash.memory.size(),
|
||||||
|
vma_structure::E_LITTLE, true));
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("BSX_RAM",
|
||||||
|
SNES::bsxcartridge.sram.data(), 0x20000000, SNES::bsxcartridge.sram.size(),
|
||||||
|
vma_structure::E_LITTLE, false));
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("BSX_PRAM",
|
||||||
|
SNES::bsxcartridge.psram.data(), 0x30000000, SNES::bsxcartridge.psram.size(),
|
||||||
|
vma_structure::E_LITTLE, false));
|
||||||
|
}
|
||||||
|
if(SNES::cartridge.mode() == SNES::Cartridge::Mode::SufamiTurbo) {
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("SLOTA_ROM", SNES::sufamiturbo.slotA.rom.data(),
|
||||||
|
0x90000000, SNES::sufamiturbo.slotA.rom.size(), vma_structure::E_LITTLE, true));
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("SLOTB_ROM", SNES::sufamiturbo.slotB.rom.data(),
|
||||||
|
0xA0000000, SNES::sufamiturbo.slotB.rom.size(), vma_structure::E_LITTLE, true));
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("SLOTA_RAM", SNES::sufamiturbo.slotA.ram.data(),
|
||||||
|
0x20000000, SNES::sufamiturbo.slotA.ram.size(), vma_structure::E_LITTLE, false));
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("SLOTB_RAM", SNES::sufamiturbo.slotB.ram.data(),
|
||||||
|
0x30000000, SNES::sufamiturbo.slotB.ram.size(), vma_structure::E_LITTLE, false));
|
||||||
|
}
|
||||||
|
if(SNES::cartridge.mode() == SNES::Cartridge::Mode::SuperGameBoy) {
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("GBROM", GameBoy::cartridge.romdata,
|
||||||
|
0x90000000, GameBoy::cartridge.romsize, vma_structure::E_LITTLE, true));
|
||||||
|
new_vma_slots.push_back(new bsnes_vma_slot("GBRAM", GameBoy::cartridge.ramdata,
|
||||||
|
0x20000000, GameBoy::cartridge.ramsize, vma_structure::E_LITTLE, false));
|
||||||
|
}
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
for(auto i : new_sram_slots)
|
for(auto i : new_sram_slots)
|
||||||
delete i;
|
delete i;
|
||||||
|
for(auto i : new_vma_slots)
|
||||||
|
delete i;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::swap(sram_slots, new_sram_slots);
|
std::swap(sram_slots, new_sram_slots);
|
||||||
|
std::swap(vma_slots, new_vma_slots);
|
||||||
for(auto i : new_sram_slots)
|
for(auto i : new_sram_slots)
|
||||||
delete i;
|
delete i;
|
||||||
|
for(auto i : new_vma_slots)
|
||||||
|
delete i;
|
||||||
}
|
}
|
||||||
|
|
18
src/interface/core.cpp
Normal file
18
src/interface/core.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include "interface/core.hpp"
|
||||||
|
|
||||||
|
sram_slot_structure::~sram_slot_structure()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
vma_structure::vma_structure(const std::string& _name, uint64_t _base, uint64_t _size, endian _rendian, bool _readonly)
|
||||||
|
{
|
||||||
|
name = _name;
|
||||||
|
base = _base;
|
||||||
|
size = _size;
|
||||||
|
rendian = _rendian;
|
||||||
|
readonly = _readonly;
|
||||||
|
}
|
||||||
|
|
||||||
|
vma_structure::~vma_structure()
|
||||||
|
{
|
||||||
|
}
|
|
@ -4,27 +4,27 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
template<typename T, typename U, U (*rfun)(uint32_t addr)>
|
template<typename T, typename U, U (*rfun)(uint64_t addr)>
|
||||||
class lua_read_memory : public lua_function
|
class lua_read_memory : public lua_function
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
lua_read_memory(const std::string& name) : lua_function(name) {}
|
lua_read_memory(const std::string& name) : lua_function(name) {}
|
||||||
int invoke(lua_State* LS)
|
int invoke(lua_State* LS)
|
||||||
{
|
{
|
||||||
uint32_t addr = get_numeric_argument<uint32_t>(LS, 1, fname.c_str());
|
uint64_t addr = get_numeric_argument<uint64_t>(LS, 1, fname.c_str());
|
||||||
lua_pushnumber(LS, static_cast<T>(rfun(addr)));
|
lua_pushnumber(LS, static_cast<T>(rfun(addr)));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, bool (*wfun)(uint32_t addr, T value)>
|
template<typename T, bool (*wfun)(uint64_t addr, T value)>
|
||||||
class lua_write_memory : public lua_function
|
class lua_write_memory : public lua_function
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
lua_write_memory(const std::string& name) : lua_function(name) {}
|
lua_write_memory(const std::string& name) : lua_function(name) {}
|
||||||
int invoke(lua_State* LS)
|
int invoke(lua_State* LS)
|
||||||
{
|
{
|
||||||
uint32_t addr = get_numeric_argument<uint32_t>(LS, 1, fname.c_str());
|
uint64_t addr = get_numeric_argument<uint64_t>(LS, 1, fname.c_str());
|
||||||
T value = get_numeric_argument<T>(LS, 2, fname.c_str());
|
T value = get_numeric_argument<T>(LS, 2, fname.c_str());
|
||||||
wfun(addr, value);
|
wfun(addr, value);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -36,47 +36,47 @@ namespace
|
||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
int handle_push_vma(lua_State* LS, std::vector<memory_region>& regions, size_t idx)
|
int handle_push_vma(lua_State* LS, std::vector<vma_structure*>& regions, size_t idx)
|
||||||
{
|
{
|
||||||
if(idx >= regions.size()) {
|
if(idx >= regions.size()) {
|
||||||
lua_pushnil(LS);
|
lua_pushnil(LS);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
memory_region& r = regions[idx];
|
vma_structure* r = regions[idx];
|
||||||
lua_newtable(LS);
|
lua_newtable(LS);
|
||||||
lua_pushstring(LS, "region_name");
|
lua_pushstring(LS, "region_name");
|
||||||
lua_pushlstring(LS, r.region_name.c_str(), r.region_name.size());
|
lua_pushlstring(LS, r->get_name().c_str(), r->get_name().size());
|
||||||
lua_settable(LS, -3);
|
lua_settable(LS, -3);
|
||||||
lua_pushstring(LS, "baseaddr");
|
lua_pushstring(LS, "baseaddr");
|
||||||
lua_pushnumber(LS, r.baseaddr);
|
lua_pushnumber(LS, r->get_base());
|
||||||
lua_settable(LS, -3);
|
lua_settable(LS, -3);
|
||||||
lua_pushstring(LS, "size");
|
lua_pushstring(LS, "size");
|
||||||
lua_pushnumber(LS, r.size);
|
lua_pushnumber(LS, r->get_size());
|
||||||
lua_settable(LS, -3);
|
lua_settable(LS, -3);
|
||||||
lua_pushstring(LS, "lastaddr");
|
lua_pushstring(LS, "lastaddr");
|
||||||
lua_pushnumber(LS, r.lastaddr);
|
lua_pushnumber(LS, r->get_base() + r->get_size() - 1);
|
||||||
lua_settable(LS, -3);
|
lua_settable(LS, -3);
|
||||||
lua_pushstring(LS, "readonly");
|
lua_pushstring(LS, "readonly");
|
||||||
lua_pushboolean(LS, r.readonly);
|
lua_pushboolean(LS, r->is_readonly());
|
||||||
lua_settable(LS, -3);
|
lua_settable(LS, -3);
|
||||||
lua_pushstring(LS, "native_endian");
|
lua_pushstring(LS, "endian");
|
||||||
lua_pushboolean(LS, r.native_endian);
|
lua_pushinteger(LS, r->get_endian());
|
||||||
lua_settable(LS, -3);
|
lua_settable(LS, -3);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function_ptr_luafun readvma("memory.read_vma", [](lua_State* LS, const std::string& fname) -> int {
|
function_ptr_luafun readvma("memory.read_vma", [](lua_State* LS, const std::string& fname) -> int {
|
||||||
std::vector<memory_region> regions = get_regions();
|
std::vector<vma_structure*> regions = get_regions();
|
||||||
uint32_t num = get_numeric_argument<uint32_t>(LS, 1, fname.c_str());
|
size_t num = get_numeric_argument<size_t>(LS, 1, fname.c_str());
|
||||||
return handle_push_vma(LS, regions, num);
|
return handle_push_vma(LS, regions, num);
|
||||||
});
|
});
|
||||||
|
|
||||||
function_ptr_luafun findvma("memory.find_vma", [](lua_State* LS, const std::string& fname) -> int {
|
function_ptr_luafun findvma("memory.find_vma", [](lua_State* LS, const std::string& fname) -> int {
|
||||||
std::vector<memory_region> regions = get_regions();
|
std::vector<vma_structure*> regions = get_regions();
|
||||||
uint32_t addr = get_numeric_argument<uint32_t>(LS, 1, fname.c_str());
|
uint64_t addr = get_numeric_argument<uint64_t>(LS, 1, fname.c_str());
|
||||||
size_t i;
|
size_t i;
|
||||||
for(i = 0; i < regions.size(); i++)
|
for(i = 0; i < regions.size(); i++)
|
||||||
if(addr >= regions[i].baseaddr && addr <= regions[i].lastaddr)
|
if(addr >= regions[i]->get_base() && addr < regions[i]->get_base() + regions[i]->get_size())
|
||||||
break;
|
break;
|
||||||
return handle_push_vma(LS, regions, i);
|
return handle_push_vma(LS, regions, i);
|
||||||
});
|
});
|
||||||
|
|
|
@ -70,10 +70,10 @@ namespace
|
||||||
&memorysearch::qword_une, &memorysearch::qword_uge, &memorysearch::qword_ugt, &memorysearch::update }
|
&memorysearch::qword_une, &memorysearch::qword_uge, &memorysearch::qword_ugt, &memorysearch::update }
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string hexformat_address(uint32_t addr)
|
std::string hexformat_address(uint64_t addr)
|
||||||
{
|
{
|
||||||
std::ostringstream x;
|
std::ostringstream x;
|
||||||
x << std::setfill('0') << std::setw(8) << std::hex << addr;
|
x << std::setfill('0') << std::setw(16) << std::hex << addr;
|
||||||
return x.str();
|
return x.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ void wxwindow_memorysearch::update()
|
||||||
runemufn([msearch, &ret, &addr_count, typecode, hexmode]() {
|
runemufn([msearch, &ret, &addr_count, typecode, hexmode]() {
|
||||||
addr_count = msearch->get_candidate_count();
|
addr_count = msearch->get_candidate_count();
|
||||||
if(addr_count <= CANDIDATE_LIMIT) {
|
if(addr_count <= CANDIDATE_LIMIT) {
|
||||||
std::list<uint32_t> addrs = msearch->get_candidates();
|
std::list<uint64_t> addrs = msearch->get_candidates();
|
||||||
for(auto i : addrs) {
|
for(auto i : addrs) {
|
||||||
std::ostringstream row;
|
std::ostringstream row;
|
||||||
row << hexformat_address(i) << " ";
|
row << hexformat_address(i) << " ";
|
||||||
|
|
Loading…
Add table
Reference in a new issue