diff --git a/Makefile b/Makefile index c5241339..817f860f 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,8 @@ gb := gb gba := gba profile := accuracy -target := higan -# target := loki +# target := higan +target := loki ifeq ($(target),loki) options += debugger diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp index cf2c9785..7ce051a2 100644 --- a/emulator/emulator.hpp +++ b/emulator/emulator.hpp @@ -3,7 +3,7 @@ namespace Emulator { static const char Name[] = "higan"; - static const char Version[] = "094.05"; + static const char Version[] = "094.06"; static const char Author[] = "byuu"; static const char License[] = "GPLv3"; static const char Website[] = "http://byuu.org/"; diff --git a/emulator/interface.hpp b/emulator/interface.hpp index 26ad8906..b46fdfe4 100644 --- a/emulator/interface.hpp +++ b/emulator/interface.hpp @@ -111,10 +111,6 @@ struct Interface { //utility functions enum class PaletteMode : unsigned { Literal, Channel, Standard, Emulation }; virtual void paletteUpdate(PaletteMode mode) {} - - //debugger functions - virtual bool tracerEnable(bool) { return false; } - virtual void exportMemory() {} }; } diff --git a/fc/cheat/cheat.cpp b/fc/cheat/cheat.cpp index 73854559..3d1e1f57 100644 --- a/fc/cheat/cheat.cpp +++ b/fc/cheat/cheat.cpp @@ -16,13 +16,13 @@ void Cheat::append(unsigned addr, unsigned comp, unsigned data) { codes.append({addr, comp, data}); } -optional Cheat::find(unsigned addr, unsigned comp) { +maybe Cheat::find(unsigned addr, unsigned comp) { for(auto& code : codes) { if(code.addr == addr && (code.comp == Unused || code.comp == comp)) { - return {true, code.data}; + return code.data; } } - return false; + return nothing; } } diff --git a/fc/cheat/cheat.hpp b/fc/cheat/cheat.hpp index c1cb490a..43f2d05c 100644 --- a/fc/cheat/cheat.hpp +++ b/fc/cheat/cheat.hpp @@ -11,7 +11,7 @@ struct Cheat { void reset(); void append(unsigned addr, unsigned data); void append(unsigned addr, unsigned comp, unsigned data); - optional find(unsigned addr, unsigned comp); + maybe find(unsigned addr, unsigned comp); }; extern Cheat cheat; diff --git a/gb/cheat/cheat.cpp b/gb/cheat/cheat.cpp index 3457d565..7b45725b 100644 --- a/gb/cheat/cheat.cpp +++ b/gb/cheat/cheat.cpp @@ -16,13 +16,13 @@ void Cheat::append(unsigned addr, unsigned comp, unsigned data) { codes.append({addr, comp, data}); } -optional Cheat::find(unsigned addr, unsigned comp) { +maybe Cheat::find(unsigned addr, unsigned comp) { for(auto& code : codes) { if(code.addr == addr && (code.comp == Unused || code.comp == comp)) { - return {true, code.data}; + return code.data; } } - return false; + return nothing; } } diff --git a/gb/cheat/cheat.hpp b/gb/cheat/cheat.hpp index c1cb490a..43f2d05c 100644 --- a/gb/cheat/cheat.hpp +++ b/gb/cheat/cheat.hpp @@ -11,7 +11,7 @@ struct Cheat { void reset(); void append(unsigned addr, unsigned data); void append(unsigned addr, unsigned comp, unsigned data); - optional find(unsigned addr, unsigned comp); + maybe find(unsigned addr, unsigned comp); }; extern Cheat cheat; diff --git a/gba/player/player.cpp b/gba/player/player.cpp index a1229532..4248b916 100644 --- a/gba/player/player.cpp +++ b/gba/player/player.cpp @@ -56,21 +56,20 @@ void Player::frame() { } } -optional Player::keyinput() { - if(status.logoDetected == false) return false; - - switch(status.logoCounter) { - case 0: return {true, 0x03ff}; - case 1: return {true, 0x03ff}; - case 2: return {true, 0x030f}; +maybe Player::keyinput() { + if(status.logoDetected) { + switch(status.logoCounter) { + case 0: return 0x03ff; + case 1: return 0x03ff; + case 2: return 0x030f; + } } - unreachable; + return nothing; } -optional Player::read() { - if(status.enable == false) return false; - - return {true, status.send}; +maybe Player::read() { + if(status.enable) return status.send; + return nothing; } void Player::write(uint8 byte, uint2 addr) { diff --git a/gba/player/player.hpp b/gba/player/player.hpp index c9280620..8b73da1a 100644 --- a/gba/player/player.hpp +++ b/gba/player/player.hpp @@ -14,8 +14,8 @@ struct Player { void power(); void frame(); - optional keyinput(); - optional read(); + maybe keyinput(); + maybe read(); void write(uint8 byte, uint2 addr); void serialize(serializer& s); diff --git a/nall/hashset.hpp b/nall/hashset.hpp index 3f51199c..58bc136f 100644 --- a/nall/hashset.hpp +++ b/nall/hashset.hpp @@ -88,19 +88,19 @@ public: length = size; } - optional find(const T& value) { - if(!pool) return false; + maybe find(const T& value) { + if(!pool) return nothing; unsigned hash = value.hash() & (length - 1); while(pool[hash]) { - if(value == *pool[hash]) return {true, *pool[hash]}; + if(value == *pool[hash]) return *pool[hash]; if(++hash >= length) hash = 0; } - return false; + return nothing; } - optional insert(const T& value) { + maybe insert(const T& value) { if(!pool) pool = new T*[length](); //double pool size when load is >= 50% @@ -111,7 +111,7 @@ public: while(pool[hash]) if(++hash >= length) hash = 0; pool[hash] = new T(value); - return {true, *pool[hash]}; + return *pool[hash]; } bool remove(const T& value) { diff --git a/nall/hid.hpp b/nall/hid.hpp index dc708886..77e67060 100644 --- a/nall/hid.hpp +++ b/nall/hid.hpp @@ -23,11 +23,11 @@ namespace HID { input.append({name}); } - optional find(const string& name) { + maybe find(const string& name) { for(unsigned id = 0; id < input.size(); id++) { - if(input[id].name == name) return {true, id}; + if(input[id].name == name) return id; } - return false; + return nothing; } }; @@ -50,11 +50,11 @@ namespace HID { group.append({name}); } - optional find(const string& name) { + maybe find(const string& name) { for(unsigned id = 0; id < group.size(); id++) { - if(group[id].name == name) return {true, id}; + if(group[id].name == name) return id; } - return false; + return nothing; } }; diff --git a/nall/ips.hpp b/nall/ips.hpp deleted file mode 100644 index 1159dee1..00000000 --- a/nall/ips.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef NALL_IPS_HPP -#define NALL_IPS_HPP - -#include -#include -#include - -namespace nall { - -struct ips { - inline bool apply(); - inline void source(const uint8_t* data, unsigned size); - inline void modify(const uint8_t* data, unsigned size); - inline ips(); - inline ~ips(); - - uint8_t* data = nullptr; - unsigned size = 0; - const uint8_t* sourceData = nullptr; - unsigned sourceSize = 0; - const uint8_t* modifyData = nullptr; - unsigned modifySize = 0; -}; - -bool ips::apply() { - if(modifySize < 8) return false; - if(modifyData[0] != 'P') return false; - if(modifyData[1] != 'A') return false; - if(modifyData[2] != 'T') return false; - if(modifyData[3] != 'C') return false; - if(modifyData[4] != 'H') return false; - - if(data) delete[] data; - data = new uint8_t[16 * 1024 * 1024 + 65536](); //maximum size of IPS patch + single-tag padding - size = sourceSize; - memcpy(data, sourceData, sourceSize); - unsigned offset = 5; - - while(true) { - unsigned address, length; - - if(offset > modifySize - 3) break; - address = modifyData[offset++] << 16; - address |= modifyData[offset++] << 8; - address |= modifyData[offset++] << 0; - - if(address == 0x454f46) { //EOF - if(offset == modifySize) return true; - if(offset == modifySize - 3) { - size = modifyData[offset++] << 16; - size |= modifyData[offset++] << 8; - size |= modifyData[offset++] << 0; - return true; - } - } - - if(offset > modifySize - 2) break; - length = modifyData[offset++] << 8; - length |= modifyData[offset++] << 0; - - if(length) { //Copy - if(offset > modifySize - length) break; - while(length--) data[address++] = modifyData[offset++]; - } else { //RLE - if(offset > modifySize - 3) break; - length = modifyData[offset++] << 8; - length |= modifyData[offset++] << 0; - if(length == 0) break; //illegal - while(length--) data[address++] = modifyData[offset]; - offset++; - } - - size = max(size, address); - } - - delete[] data; - data = nullptr; - return false; -} - -void ips::source(const uint8_t* data, unsigned size) { - sourceData = data, sourceSize = size; -} - -void ips::modify(const uint8_t* data, unsigned size) { - modifyData = data, modifySize = size; -} - -ips::ips() { -} - -ips::~ips() { - if(data) delete[] data; - if(sourceData) delete[] sourceData; - if(modifyData) delete[] modifyData; -} - -} - -#endif diff --git a/nall/map.hpp b/nall/map.hpp index 56e4b5c8..72c99ea5 100644 --- a/nall/map.hpp +++ b/nall/map.hpp @@ -16,9 +16,9 @@ template struct map { node_t(const T& key, const U& value) : key(key), value(value) {} }; - optional find(const T& key) const { - if(auto node = root.find({key})) return {true, node().value}; - return false; + maybe find(const T& key) const { + if(auto node = root.find({key})) return node().value; + return nothing; } void insert(const T& key, const U& value) { root.insert({key, value}); } @@ -36,8 +36,8 @@ protected: }; template struct bimap { - optional find(const T& key) const { return tmap.find(key); } - optional find(const U& key) const { return umap.find(key); } + maybe find(const T& key) const { return tmap.find(key); } + maybe find(const U& key) const { return umap.find(key); } void insert(const T& key, const U& value) { tmap.insert(key, value); umap.insert(value, key); } void remove(const T& key) { if(auto p = tmap.find(key)) { umap.remove(p().value); tmap.remove(key); } } void remove(const U& key) { if(auto p = umap.find(key)) { tmap.remove(p().value); umap.remove(key); } } diff --git a/nall/maybe.hpp b/nall/maybe.hpp new file mode 100644 index 00000000..4f806dac --- /dev/null +++ b/nall/maybe.hpp @@ -0,0 +1,76 @@ +#ifndef NALL_MAYBE_HPP +#define NALL_MAYBE_HPP + +namespace nall { + +struct nothing_t {}; +static nothing_t nothing; + +template +class maybe { + T* value = nullptr; + +public: + maybe() {} + maybe(nothing_t) {} + maybe(const T& source) { operator=(source); } + maybe(const maybe& source) { operator=(source); } + maybe(maybe&& source) { operator=(std::move(source)); } + ~maybe() { reset(); } + + maybe& operator=(nothing_t) { reset(); return *this; } + maybe& operator=(const T& source) { reset(); value = new T(source); return *this; } + maybe& operator=(const maybe& source) { reset(); if(source) value = new T(source()); return *this; } + maybe& operator=(maybe&& source) { reset(); value = source.value; source.value = nullptr; return *this; } + + bool operator==(const maybe& source) const { + if(value && source.value) return *value == *source.value; + return !value && !source.value; + } + bool operator!=(const maybe& source) const { return !operator==(source); } + + explicit operator bool() const { return value; } + T& operator()() { assert(value); return *value; } + const T& operator()() const { assert(value); return *value; } + const T& operator()(const T& invalid) const { if(value) return *value; return invalid; } + + bool empty() const { return value == nullptr; } + void reset() { if(value) { delete value; value = nullptr; } } + void swap(maybe& source) { std::swap(value, source.value); } +}; + +template +class maybe { + T* value = nullptr; + +public: + maybe() {} + maybe(nothing_t) {} + maybe(const T& source) { operator=(source); } + maybe(const maybe& source) { operator=(source); } + maybe(maybe&& source) { operator=(std::move(source)); } + + maybe& operator=(nothing_t) { value = nullptr; return *this; } + maybe& operator=(const T& source) { value = (T*)&source; return *this; } + maybe& operator=(const maybe& source) { value = source.value; return *this; } + maybe& operator=(maybe&& source) { value = source.value; source.value = nullptr; return *this; } + + bool operator==(const maybe& source) const { + if(value && source.value) return *value == *source.value; + return !value && !source.value; + } + bool operator!=(const maybe& source) const { return !operator==(source); } + + explicit operator bool() const { return value; } + T& operator()() { assert(value); return *value; } + const T& operator()() const { assert(value); return *value; } + const T& operator()(const T& invalid) const { if(value) return *value; return invalid; } + + bool empty() const { return value == nullptr; } + void reset() { value = nullptr; } + void swap(maybe& source) { std::swap(value, source.value); } +}; + +} + +#endif diff --git a/nall/nall.hpp b/nall/nall.hpp index 871e2d51..0b56d50a 100644 --- a/nall/nall.hpp +++ b/nall/nall.hpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include diff --git a/nall/set.hpp b/nall/set.hpp index c8003ec0..d463296d 100644 --- a/nall/set.hpp +++ b/nall/set.hpp @@ -45,22 +45,22 @@ template struct set { nodes = 0; } - optional find(const T& value) { + maybe find(const T& value) { if(node_t* node = find(root, value)) return node->value; - return false; + return nothing; } - optional find(const T& value) const { + maybe find(const T& value) const { if(node_t* node = find(root, value)) return node->value; - return false; + return nothing; } - optional insert(const T& value) { + maybe insert(const T& value) { unsigned count = size(); node_t* v = insert(root, value); root->red = 0; - if(size() == count) return false; - return {true, v->value}; + if(size() == count) return nothing; + return v->value; } template bool insert(const T& value, Args&&... args) { diff --git a/nall/string/base.hpp b/nall/string/base.hpp index 7ba6f0fc..8da9d880 100644 --- a/nall/string/base.hpp +++ b/nall/string/base.hpp @@ -107,10 +107,10 @@ public: inline string& strip(); - inline optional find(rstring key) const; - inline optional ifind(rstring key) const; - inline optional qfind(rstring key) const; - inline optional iqfind(rstring key) const; + inline maybe find(rstring key) const; + inline maybe ifind(rstring key) const; + inline maybe qfind(rstring key) const; + inline maybe iqfind(rstring key) const; //core.hpp inline explicit operator bool() const; @@ -155,7 +155,7 @@ public: //list.hpp struct lstring : vector { - inline optional find(rstring) const; + inline maybe find(rstring) const; inline string merge(const string&) const; inline lstring& isort(); inline lstring& strip(); diff --git a/nall/string/char/base.hpp b/nall/string/char/base.hpp index 0a029b2d..49b2fc22 100644 --- a/nall/string/char/base.hpp +++ b/nall/string/char/base.hpp @@ -36,11 +36,11 @@ inline bool strccat(char* target, const char* source, unsigned length); inline void strpcpy(char*& target, const char* source, unsigned& length); //strpos.hpp -inline optional strpos(const char* str, const char* key); -inline optional istrpos(const char* str, const char* key); -inline optional qstrpos(const char* str, const char* key); -inline optional iqstrpos(const char* str, const char* key); -template inline optional ustrpos(const char* str, const char* key); +inline maybe strpos(const char* str, const char* key); +inline maybe istrpos(const char* str, const char* key); +inline maybe qstrpos(const char* str, const char* key); +inline maybe iqstrpos(const char* str, const char* key); +template inline maybe ustrpos(const char* str, const char* key); //trim.hpp template inline char* ltrim(char* str, const char* key = " "); diff --git a/nall/string/char/strpos.hpp b/nall/string/char/strpos.hpp index 19c23217..8c0baa44 100644 --- a/nall/string/char/strpos.hpp +++ b/nall/string/char/strpos.hpp @@ -7,26 +7,26 @@ namespace nall { template -optional ustrpos(const char* str, const char* key) { +maybe ustrpos(const char* str, const char* key) { const char* base = str; while(*str) { if(quoteskip(str)) continue; for(unsigned n = 0;; n++) { - if(key[n] == 0) return {true, (unsigned)(str - base)}; - if(str[n] == 0) return false; + if(key[n] == 0) return (unsigned)(str - base); + if(str[n] == 0) return nothing; if(!chrequal(str[n], key[n])) break; } str++; } - return false; + return nothing; } -optional strpos(const char* str, const char* key) { return ustrpos(str, key); } -optional istrpos(const char* str, const char* key) { return ustrpos(str, key); } -optional qstrpos(const char* str, const char* key) { return ustrpos(str, key); } -optional iqstrpos(const char* str, const char* key) { return ustrpos(str, key); } +maybe strpos(const char* str, const char* key) { return ustrpos(str, key); } +maybe istrpos(const char* str, const char* key) { return ustrpos(str, key); } +maybe qstrpos(const char* str, const char* key) { return ustrpos(str, key); } +maybe iqstrpos(const char* str, const char* key) { return ustrpos(str, key); } } diff --git a/nall/string/eval/evaluator.hpp b/nall/string/eval/evaluator.hpp index 49ac851e..8957a30c 100644 --- a/nall/string/eval/evaluator.hpp +++ b/nall/string/eval/evaluator.hpp @@ -93,16 +93,16 @@ inline int64_t evaluateInteger(Node* node) { throw "invalid operator"; } -inline optional integer(const string& expression) { +inline maybe integer(const string& expression) { try { auto tree = new Node; const char* p = expression; parse(tree, p, 0); auto result = evaluateInteger(tree); delete tree; - return {true, result}; + return result; } catch(const char*) { - return false; + return nothing; } } @@ -138,16 +138,16 @@ inline long double evaluateReal(Node* node) { throw "invalid operator"; } -inline optional real(const string& expression) { +inline maybe real(const string& expression) { try { auto tree = new Node; const char* p = expression; parse(tree, p, 0); auto result = evaluateReal(tree); delete tree; - return {true, result}; + return result; } catch(const char*) { - return false; + return nothing; } } diff --git a/nall/string/list.hpp b/nall/string/list.hpp index 196a7a56..55b2e76e 100644 --- a/nall/string/list.hpp +++ b/nall/string/list.hpp @@ -2,11 +2,11 @@ namespace nall { -optional lstring::find(rstring key) const { +maybe lstring::find(rstring key) const { for(unsigned i = 0; i < size(); i++) { - if(operator[](i) == key) return {true, i}; + if(operator[](i) == key) return i; } - return false; + return nothing; } string lstring::merge(const string& separator) const { diff --git a/nall/string/wrapper.hpp b/nall/string/wrapper.hpp index 0422ecdc..0eadf3dd 100644 --- a/nall/string/wrapper.hpp +++ b/nall/string/wrapper.hpp @@ -114,10 +114,10 @@ string& string::strip() { return *this; } -optional string::find(rstring key) const { return strpos(data(), key); } -optional string::ifind(rstring key) const { return istrpos(data(), key); } -optional string::qfind(rstring key) const { return qstrpos(data(), key); } -optional string::iqfind(rstring key) const { return iqstrpos(data(), key); } +maybe string::find(rstring key) const { return strpos(data(), key); } +maybe string::ifind(rstring key) const { return istrpos(data(), key); } +maybe string::qfind(rstring key) const { return qstrpos(data(), key); } +maybe string::iqfind(rstring key) const { return iqstrpos(data(), key); } } diff --git a/nall/ups.hpp b/nall/ups.hpp deleted file mode 100644 index d26a6519..00000000 --- a/nall/ups.hpp +++ /dev/null @@ -1,225 +0,0 @@ -#ifndef NALL_UPS_HPP -#define NALL_UPS_HPP - -#include -#include -#include -#include - -namespace nall { - -struct ups { - enum class result : unsigned { - unknown, - success, - patch_unwritable, - patch_invalid, - source_invalid, - target_invalid, - target_too_small, - patch_checksum_invalid, - source_checksum_invalid, - target_checksum_invalid, - }; - - function progress; - - result create( - const uint8_t* sourcedata, unsigned sourcelength, - const uint8_t* targetdata, unsigned targetlength, - const char* patchfilename - ) { - source_data = (uint8_t*)sourcedata, target_data = (uint8_t*)targetdata; - source_length = sourcelength, target_length = targetlength; - source_offset = target_offset = 0; - source_checksum = target_checksum = patch_checksum = ~0; - - if(patch_file.open(patchfilename, file::mode::write) == false) return result::patch_unwritable; - - patch_write('U'); - patch_write('P'); - patch_write('S'); - patch_write('1'); - encode(source_length); - encode(target_length); - - unsigned output_length = source_length > target_length ? source_length : target_length; - unsigned relative = 0; - for(unsigned offset = 0; offset < output_length;) { - uint8_t x = source_read(); - uint8_t y = target_read(); - - if(x == y) { - offset++; - continue; - } - - encode(offset++ - relative); - patch_write(x ^ y); - - while(true) { - if(offset >= output_length) { - patch_write(0x00); - break; - } - - x = source_read(); - y = target_read(); - offset++; - patch_write(x ^ y); - if(x == y) break; - } - - relative = offset; - } - - source_checksum = ~source_checksum; - target_checksum = ~target_checksum; - for(unsigned i = 0; i < 4; i++) patch_write(source_checksum >> (i * 8)); - for(unsigned i = 0; i < 4; i++) patch_write(target_checksum >> (i * 8)); - uint32_t patch_result_checksum = ~patch_checksum; - for(unsigned i = 0; i < 4; i++) patch_write(patch_result_checksum >> (i * 8)); - - patch_file.close(); - return result::success; - } - - result apply( - const uint8_t* patchdata, unsigned patchlength, - const uint8_t* sourcedata, unsigned sourcelength, - uint8_t* targetdata, unsigned& targetlength - ) { - patch_data = (uint8_t*)patchdata, source_data = (uint8_t*)sourcedata, target_data = targetdata; - patch_length = patchlength, source_length = sourcelength, target_length = targetlength; - patch_offset = source_offset = target_offset = 0; - patch_checksum = source_checksum = target_checksum = ~0; - - if(patch_length < 18) return result::patch_invalid; - if(patch_read() != 'U') return result::patch_invalid; - if(patch_read() != 'P') return result::patch_invalid; - if(patch_read() != 'S') return result::patch_invalid; - if(patch_read() != '1') return result::patch_invalid; - - unsigned source_read_length = decode(); - unsigned target_read_length = decode(); - - if(source_length != source_read_length && source_length != target_read_length) return result::source_invalid; - targetlength = (source_length == source_read_length ? target_read_length : source_read_length); - if(target_length < targetlength) return result::target_too_small; - target_length = targetlength; - - while(patch_offset < patch_length - 12) { - unsigned length = decode(); - while(length--) target_write(source_read()); - while(true) { - uint8_t patch_xor = patch_read(); - target_write(patch_xor ^ source_read()); - if(patch_xor == 0) break; - } - } - while(source_offset < source_length) target_write(source_read()); - while(target_offset < target_length) target_write(source_read()); - - uint32_t patch_read_checksum = 0, source_read_checksum = 0, target_read_checksum = 0; - for(unsigned i = 0; i < 4; i++) source_read_checksum |= patch_read() << (i * 8); - for(unsigned i = 0; i < 4; i++) target_read_checksum |= patch_read() << (i * 8); - uint32_t patch_result_checksum = ~patch_checksum; - source_checksum = ~source_checksum; - target_checksum = ~target_checksum; - for(unsigned i = 0; i < 4; i++) patch_read_checksum |= patch_read() << (i * 8); - - if(patch_result_checksum != patch_read_checksum) return result::patch_invalid; - if(source_checksum == source_read_checksum && source_length == source_read_length) { - if(target_checksum == target_read_checksum && target_length == target_read_length) return result::success; - return result::target_invalid; - } else if(source_checksum == target_read_checksum && source_length == target_read_length) { - if(target_checksum == source_read_checksum && target_length == source_read_length) return result::success; - return result::target_invalid; - } else { - return result::source_invalid; - } - } - -private: - uint8_t* patch_data = nullptr; - uint8_t* source_data = nullptr; - uint8_t* target_data = nullptr; - unsigned patch_length, source_length, target_length; - unsigned patch_offset, source_offset, target_offset; - unsigned patch_checksum, source_checksum, target_checksum; - file patch_file; - - uint8_t patch_read() { - if(patch_offset < patch_length) { - uint8_t n = patch_data[patch_offset++]; - patch_checksum = crc32_adjust(patch_checksum, n); - return n; - } - return 0x00; - } - - uint8_t source_read() { - if(source_offset < source_length) { - uint8_t n = source_data[source_offset++]; - source_checksum = crc32_adjust(source_checksum, n); - return n; - } - return 0x00; - } - - uint8_t target_read() { - uint8_t result = 0x00; - if(target_offset < target_length) { - result = target_data[target_offset]; - target_checksum = crc32_adjust(target_checksum, result); - } - if(((target_offset++ & 255) == 0) && progress) { - progress(target_offset, source_length > target_length ? source_length : target_length); - } - return result; - } - - void patch_write(uint8_t n) { - patch_file.write(n); - patch_checksum = crc32_adjust(patch_checksum, n); - } - - void target_write(uint8_t n) { - if(target_offset < target_length) { - target_data[target_offset] = n; - target_checksum = crc32_adjust(target_checksum, n); - } - if(((target_offset++ & 255) == 0) && progress) { - progress(target_offset, source_length > target_length ? source_length : target_length); - } - } - - void encode(uint64_t offset) { - while(true) { - uint64_t x = offset & 0x7f; - offset >>= 7; - if(offset == 0) { - patch_write(0x80 | x); - break; - } - patch_write(x); - offset--; - } - } - - uint64_t decode() { - uint64_t offset = 0, shift = 1; - while(true) { - uint8_t x = patch_read(); - offset += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - offset += shift; - } - return offset; - } -}; - -} - -#endif diff --git a/nall/utility.hpp b/nall/utility.hpp index 25609a7c..f574a76b 100644 --- a/nall/utility.hpp +++ b/nall/utility.hpp @@ -1,9 +1,7 @@ #ifndef NALL_UTILITY_HPP #define NALL_UTILITY_HPP -#include #include -#include namespace nall { @@ -12,120 +10,6 @@ template struct base_from_member { base_from_member(T value) : value(value) {} }; -template struct ref { - T& operator*() { - if(type == Type::Reference) return *any_cast(value); - return any_cast(value); - } - - operator T&() { return operator*(); } - - ref(T& value) : type(Type::Reference), value(&value) {} - ref(T&& value) : type(Type::Temporary), value(value) {} - -protected: - enum class Type : unsigned { Reference, Temporary } type; - any value; -}; - -template struct optional { - typedef typename std::remove_reference::type T; - static const bool isConst = std::is_const::value; - static const bool isReference = std::is_reference::value; - struct optional_value_not_valid{}; - - bool valid = false; - T* value = nullptr; - - operator bool() const { return valid; } - - void reset() { - valid = false; - if(value) { - if(!isReference) delete value; - value = nullptr; - } - } - - template::type> - T& operator*() { - if(!valid) throw optional_value_not_valid{}; - return *value; - } - - template::type> - T& operator()() { - if(!valid) throw optional_value_not_valid{}; - return *value; - } - - const T& operator*() const { - if(!valid) throw optional_value_not_valid{}; - return *value; - } - - const T& operator()() const { - if(!valid) throw optional_value_not_valid{}; - return *value; - } - - const T& operator()(const T& alternate) const { - if(!valid) return alternate; - return *value; - } - - const bool operator==(const optional& source) const { - if(valid && source.valid) return *value == *source.value; - if(!valid && !source.valid) return true; - return false; - } - - const bool operator!=(const optional& source) const { - return !operator==(source); - } - - optional& operator=(const T& source) { - reset(); - valid = true; - if(isReference) value = (T*)&source; - else value = new T(source); - return *this; - } - - optional& operator=(T&& source) { - reset(); - valid = true; - if(isReference) value = &source; - else value = new T(std::move(source)); - return *this; - } - - optional& operator=(const optional& source) { - reset(); - if(source) operator=(source()); - return *this; - } - - optional& operator=(optional&& source) { - reset(); - valid = source.valid; - value = source.value; - source.valid = false; - source.value = nullptr; - return *this; - } - - optional() = default; - optional(bool valid) : valid(valid) {} - optional(const T& value) { operator=(value); } - optional(T&& value) { operator=(std::move(value)); } - optional(bool valid, const T& value) : valid(valid) { if(valid) operator=(value); } - optional(bool valid, T&& value) : valid(valid) { if(valid) operator=(std::move(value)); } - optional(const optional& source) { operator=(source); } - optional(optional&& source) { operator=(std::move(source)); } - ~optional() { reset(); } -}; - template inline T* allocate(unsigned size, const T& value) { T* array = new T[size]; for(unsigned i = 0; i < size; i++) array[i] = value; diff --git a/nall/vector.hpp b/nall/vector.hpp index 7ccb53db..d1da089b 100644 --- a/nall/vector.hpp +++ b/nall/vector.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -164,9 +165,9 @@ public: nall::sort(pool + poolbase, objectsize, lessthan); } - optional find(const T& data) { - for(unsigned n = 0; n < objectsize; n++) if(pool[poolbase + n] == data) return {true, n}; - return false; + maybe find(const T& data) { + for(unsigned n = 0; n < objectsize; n++) if(pool[poolbase + n] == data) return n; + return nothing; } T& first() { diff --git a/phoenix/gtk/font.cpp b/phoenix/gtk/font.cpp index 750d47d4..41232cbd 100644 --- a/phoenix/gtk/font.cpp +++ b/phoenix/gtk/font.cpp @@ -36,8 +36,8 @@ PangoFontDescription* pFont::create(string description) { if(part[0] != "") family = part[0]; if(part.size() >= 2) size = decimal(part[1]); - if(part.size() >= 3) bold = part[2].find("Bold"); - if(part.size() >= 3) italic = part[2].find("Italic"); + if(part.size() >= 3) bold = (bool)part[2].find("Bold"); + if(part.size() >= 3) italic = (bool)part[2].find("Italic"); PangoFontDescription* font = pango_font_description_new(); pango_font_description_set_family(font, family); diff --git a/phoenix/gtk/platform.hpp b/phoenix/gtk/platform.hpp index 5c86bc11..e3050f8c 100644 --- a/phoenix/gtk/platform.hpp +++ b/phoenix/gtk/platform.hpp @@ -347,8 +347,9 @@ struct pConsole : public pWidget { Console& console; GtkWidget* subWidget; GtkTextBuffer* textBuffer; - string command; string previousPrompt; + lstring history; + unsigned historyOffset = 0; void print(string text); void reset(); @@ -359,7 +360,8 @@ struct pConsole : public pWidget { void destructor(); void orphan(); bool keyPress(unsigned scancode, unsigned mask); - void seekCursorToEnd(); + void seekToEnd(); + void seekToMark(); }; struct pFrame : public pWidget { diff --git a/phoenix/gtk/widget/console.cpp b/phoenix/gtk/widget/console.cpp index 44d71436..b44db5bf 100644 --- a/phoenix/gtk/widget/console.cpp +++ b/phoenix/gtk/widget/console.cpp @@ -5,34 +5,28 @@ static bool Console_keyPress(GtkWidget* widget, GdkEventKey* event, Console* sel } void pConsole::print(string text) { - //insert text before prompt and command, so as not to interrupt the current command + //insert text before prompt and command GtkTextIter iter; - gtk_text_buffer_get_end_iter(textBuffer, &iter); - gtk_text_iter_set_offset(&iter, gtk_text_iter_get_offset(&iter) - console.prompt().size() - command.size()); + gtk_text_buffer_get_iter_at_line_offset(textBuffer, &iter, gtk_text_buffer_get_line_count(textBuffer), 0); gtk_text_buffer_insert(textBuffer, &iter, text, -1); - seekCursorToEnd(); + seekToEnd(); } void pConsole::reset() { - //flush history and command; draw prompt - command.reset(); + //flush history and redraw prompt gtk_text_buffer_set_text(textBuffer, console.prompt(), -1); - seekCursorToEnd(); + seekToEnd(); } void pConsole::setPrompt(string prompt) { - //erase old prompt; insert new prompt in its place - GtkTextIter lhs, rhs, iter; - gtk_text_buffer_get_end_iter(textBuffer, &lhs); - gtk_text_buffer_get_end_iter(textBuffer, &rhs); - gtk_text_iter_set_offset(&lhs, gtk_text_iter_get_offset(&lhs) - previousPrompt.size() - command.size()); - gtk_text_iter_set_offset(&rhs, gtk_text_iter_get_offset(&rhs) - command.size()); + //erase previous prompt and replace it with new prompt + GtkTextIter lhs, rhs; + gtk_text_buffer_get_iter_at_line_offset(textBuffer, &lhs, gtk_text_buffer_get_line_count(textBuffer), 0); + gtk_text_buffer_get_iter_at_line_offset(textBuffer, &rhs, gtk_text_buffer_get_line_count(textBuffer), previousPrompt.size()); gtk_text_buffer_delete(textBuffer, &lhs, &rhs); - gtk_text_buffer_get_end_iter(textBuffer, &iter); - gtk_text_iter_set_offset(&iter, gtk_text_iter_get_offset(&iter) - command.size()); - gtk_text_buffer_insert(textBuffer, &iter, prompt, -1); - seekCursorToEnd(); - previousPrompt = prompt; + gtk_text_buffer_get_iter_at_line_offset(textBuffer, &lhs, gtk_text_buffer_get_line_count(textBuffer), 0); + gtk_text_buffer_insert(textBuffer, &lhs, previousPrompt = prompt, -1); + seekToEnd(); } void pConsole::constructor() { @@ -47,7 +41,7 @@ void pConsole::constructor() { textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(subWidget)); - GdkColor background = CreateColor(48, 24, 24); + GdkColor background = CreateColor(72, 24, 24); gtk_widget_modify_base(subWidget, GTK_STATE_NORMAL, &background); GdkColor foreground = CreateColor(255, 255, 255); gtk_widget_modify_text(subWidget, GTK_STATE_NORMAL, &foreground); @@ -70,50 +64,116 @@ void pConsole::orphan() { bool pConsole::keyPress(unsigned scancode, unsigned mask) { if(mask & (GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_SUPER_MASK)) return false; //allow actions such as Ctrl+C (copy) + GtkTextMark* mark = gtk_text_buffer_get_mark(textBuffer, "insert"); + GtkTextIter start, cursor, end; + gtk_text_buffer_get_iter_at_line_offset(textBuffer, &start, gtk_text_buffer_get_line_count(textBuffer), console.prompt().size()); + gtk_text_buffer_get_iter_at_mark(textBuffer, &cursor, mark); + gtk_text_buffer_get_end_iter(textBuffer, &end); + if(scancode == GDK_KEY_Return || scancode == GDK_KEY_KP_Enter) { - //add current prompt and command to history; print new prompt; execute command - GtkTextIter iter; - gtk_text_buffer_get_end_iter(textBuffer, &iter); - gtk_text_buffer_insert(textBuffer, &iter, string{"\n", console.prompt()}, -1); - string s = command; - command.reset(); + char* temp = gtk_text_buffer_get_text(textBuffer, &start, &end, true); + string s = temp; + g_free(temp); + gtk_text_buffer_insert(textBuffer, &end, string{"\n", console.prompt()}, -1); if(console.onActivate) console.onActivate(s); - seekCursorToEnd(); + if(s) history.prepend(s); + if(history.size() > 128) history.removeLast(); + historyOffset = 0; + seekToEnd(); + return true; + } + + if(scancode == GDK_KEY_Up) { + gtk_text_buffer_delete(textBuffer, &start, &end); + gtk_text_buffer_get_end_iter(textBuffer, &end); + if(historyOffset < history.size()) { + gtk_text_buffer_insert(textBuffer, &end, history[historyOffset++], -1); + } + seekToEnd(); + return true; + } + + if(scancode == GDK_KEY_Down) { + gtk_text_buffer_delete(textBuffer, &start, &end); + gtk_text_buffer_get_end_iter(textBuffer, &end); + if(historyOffset > 0) { + gtk_text_buffer_insert(textBuffer, &end, history[--historyOffset], -1); + } + seekToEnd(); + return true; + } + + if(scancode == GDK_KEY_Left) { + if(gtk_text_iter_get_offset(&cursor) <= gtk_text_iter_get_offset(&start)) { + gtk_text_buffer_place_cursor(textBuffer, &start); + } else { + gtk_text_iter_set_offset(&cursor, gtk_text_iter_get_offset(&cursor) - 1); + gtk_text_buffer_place_cursor(textBuffer, &cursor); + } + seekToMark(); + return true; + } + + if(scancode == GDK_KEY_Right) { + if(gtk_text_iter_get_offset(&cursor) < gtk_text_iter_get_offset(&start)) { + gtk_text_buffer_place_cursor(textBuffer, &end); + } else if(gtk_text_iter_get_offset(&cursor) < gtk_text_iter_get_offset(&end)) { + gtk_text_iter_set_offset(&cursor, gtk_text_iter_get_offset(&cursor) + 1); + gtk_text_buffer_place_cursor(textBuffer, &cursor); + } + seekToMark(); + return true; + } + + if(scancode == GDK_KEY_Home) { + gtk_text_buffer_place_cursor(textBuffer, &start); + seekToMark(); + return true; + } + + if(scancode == GDK_KEY_End) { + gtk_text_buffer_place_cursor(textBuffer, &end); + seekToMark(); return true; } if(scancode == GDK_KEY_BackSpace) { - if(command.size()) { - //delete last character of command - command.resize(command.size() - 1); - GtkTextIter lhs, rhs; - gtk_text_buffer_get_end_iter(textBuffer, &lhs); - gtk_text_buffer_get_end_iter(textBuffer, &rhs); - gtk_text_iter_set_offset(&lhs, gtk_text_iter_get_offset(&lhs) - 1); - gtk_text_buffer_delete(textBuffer, &lhs, &rhs); - } - seekCursorToEnd(); + if(gtk_text_iter_get_offset(&cursor) <= gtk_text_iter_get_offset(&start)) return true; + GtkTextIter lhs = cursor; + gtk_text_iter_set_offset(&lhs, gtk_text_iter_get_offset(&cursor) - 1); + gtk_text_buffer_delete(textBuffer, &lhs, &cursor); + seekToMark(); + return true; + } + + if(scancode == GDK_KEY_Delete) { + if(gtk_text_iter_get_offset(&cursor) < gtk_text_iter_get_offset(&start)) return true; + if(gtk_text_iter_get_offset(&cursor) == gtk_text_iter_get_offset(&end)) return true; + GtkTextIter rhs = cursor; + gtk_text_iter_set_offset(&rhs, gtk_text_iter_get_offset(&cursor) + 1); + gtk_text_buffer_delete(textBuffer, &cursor, &rhs); + seekToMark(); return true; } if(scancode >= 0x20 && scancode <= 0x7e) { - //add character to end of command - GtkTextIter iter; - gtk_text_buffer_get_end_iter(textBuffer, &iter); - gtk_text_buffer_insert(textBuffer, &iter, string{(char)scancode}, -1); - seekCursorToEnd(); - command.append((char)scancode); + if(gtk_text_iter_get_offset(&cursor) < gtk_text_iter_get_offset(&start)) return true; + gtk_text_buffer_insert(textBuffer, &cursor, string{(char)scancode}, -1); + seekToMark(); return true; } return false; } -void pConsole::seekCursorToEnd() { - //place cursor at end of text buffer; scroll text view to the cursor to ensure it is visible +void pConsole::seekToEnd() { GtkTextIter iter; gtk_text_buffer_get_end_iter(textBuffer, &iter); gtk_text_buffer_place_cursor(textBuffer, &iter); + seekToMark(); +} + +void pConsole::seekToMark() { GtkTextMark* mark = gtk_text_buffer_get_mark(textBuffer, "insert"); gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(subWidget), mark); } diff --git a/phoenix/qt/font.cpp b/phoenix/qt/font.cpp index ce1a6832..3c6fe572 100644 --- a/phoenix/qt/font.cpp +++ b/phoenix/qt/font.cpp @@ -34,8 +34,8 @@ QFont pFont::create(string description) { if(part[0] != "") family = part[0]; if(part.size() >= 2) size = decimal(part[1]); - if(part.size() >= 3) bold = part[2].find("Bold"); - if(part.size() >= 3) italic = part[2].find("Italic"); + if(part.size() >= 3) bold = (bool)part[2].find("Bold"); + if(part.size() >= 3) italic = (bool)part[2].find("Italic"); QFont qtFont; qtFont.setFamily(family); diff --git a/phoenix/qt/platform.moc b/phoenix/qt/platform.moc index 6fd7d8aa..91fc08f6 100644 --- a/phoenix/qt/platform.moc +++ b/phoenix/qt/platform.moc @@ -1,7 +1,7 @@ /**************************************************************************** ** Meta object code from reading C++ file 'platform.moc.hpp' ** -** Created: Wed Jan 29 08:08:49 2014 +** Created: Wed Feb 5 08:24:19 2014 ** by: The Qt Meta Object Compiler version 63 (Qt 4.8.2) ** ** WARNING! All changes made in this file will be lost! diff --git a/phoenix/windows/font.cpp b/phoenix/windows/font.cpp index 19781143..94db0ecf 100644 --- a/phoenix/windows/font.cpp +++ b/phoenix/windows/font.cpp @@ -37,8 +37,8 @@ HFONT pFont::create(string description) { if(part[0] != "") family = part[0]; if(part.size() >= 2) size = decimal(part[1]); - if(part.size() >= 3) bold = part[2].find("Bold"); - if(part.size() >= 3) italic = part[2].find("Italic"); + if(part.size() >= 3) bold = (bool)part[2].find("Bold"); + if(part.size() >= 3) italic = (bool)part[2].find("Italic"); return CreateFont( -(size * 96.0 / 72.0 + 0.5), diff --git a/processor/spc700/disassembler.cpp b/processor/spc700/disassembler.cpp index 9c95d2e1..fbbde16e 100644 --- a/processor/spc700/disassembler.cpp +++ b/processor/spc700/disassembler.cpp @@ -1,4 +1,4 @@ -string SPC700::disassemble_opcode(uint16 addr) { +string SPC700::disassemble_opcode(uint16 addr, bool p) { auto read = [&](uint16 addr) -> uint8 { return disassembler_read(addr); }; @@ -11,7 +11,7 @@ string SPC700::disassemble_opcode(uint16 addr) { auto a = [&] { return hex<4>((read(addr + 1) << 0) + (read(addr + 2) << 8)); }; auto b = [&](unsigned n) { return hex<2>(read(addr + 1 + n)); }; auto r = [&](unsigned r, unsigned n = 0) { return hex<4>(addr + r + (int8)read(addr + 1 + n)); }; - auto dp = [&](unsigned n) { return hex<3>((regs.p.p << 8) + read(addr + 1 + n)); }; + auto dp = [&](unsigned n) { return hex<3>((p << 8) + read(addr + 1 + n)); }; auto ab = [&] { unsigned n = (read(addr + 1) << 0) + (read(addr + 2) << 8); return string{ hex<4>(n & 0x1fff), ":", hex<1>(n >> 13) }; diff --git a/processor/spc700/spc700.hpp b/processor/spc700/spc700.hpp index 5ff3a40a..68ee7a85 100644 --- a/processor/spc700/spc700.hpp +++ b/processor/spc700/spc700.hpp @@ -19,7 +19,7 @@ struct SPC700 { uint8 opcode; void serialize(serializer&); - string disassemble_opcode(uint16 addr); + string disassemble_opcode(uint16 addr, bool p); protected: uint8 op_adc(uint8, uint8); diff --git a/sfc/cheat/cheat.cpp b/sfc/cheat/cheat.cpp index 9dcdd54f..8eee902e 100644 --- a/sfc/cheat/cheat.cpp +++ b/sfc/cheat/cheat.cpp @@ -17,16 +17,16 @@ void Cheat::append(unsigned addr, unsigned comp, unsigned data) { codes.append({addr, comp, data}); } -optional Cheat::find(unsigned addr, unsigned comp) { +maybe Cheat::find(unsigned addr, unsigned comp) { //WRAM mirroring: $00-3f,80-bf:0000-1fff -> $7e:0000-1fff if((addr & 0x40e000) == 0x000000) addr = 0x7e0000 | (addr & 0x1fff); for(auto& code : codes) { if(code.addr == addr && (code.comp == Unused || code.comp == comp)) { - return {true, code.data}; + return code.data; } } - return false; + return nothing; } } diff --git a/sfc/cheat/cheat.hpp b/sfc/cheat/cheat.hpp index c1cb490a..43f2d05c 100644 --- a/sfc/cheat/cheat.hpp +++ b/sfc/cheat/cheat.hpp @@ -11,7 +11,7 @@ struct Cheat { void reset(); void append(unsigned addr, unsigned data); void append(unsigned addr, unsigned comp, unsigned data); - optional find(unsigned addr, unsigned comp); + maybe find(unsigned addr, unsigned comp); }; extern Cheat cheat; diff --git a/sfc/cpu/cpu.cpp b/sfc/cpu/cpu.cpp index 1f01a9d0..4aa60e8e 100644 --- a/sfc/cpu/cpu.cpp +++ b/sfc/cpu/cpu.cpp @@ -86,12 +86,6 @@ void CPU::enter() { void CPU::op_step() { debugger.op_exec(regs.pc.d); - if(interface->tracer.open()) { - char text[4096]; - disassemble_opcode(text); - interface->tracer.print(text, "\n"); - } - (this->*opcode_table[op_readpc()])(); } diff --git a/sfc/interface/interface.cpp b/sfc/interface/interface.cpp index 41d1f763..66b7c643 100644 --- a/sfc/interface/interface.cpp +++ b/sfc/interface/interface.cpp @@ -270,7 +270,6 @@ void Interface::save(unsigned id, const stream& stream) { void Interface::unload() { save(); cartridge.unload(); - tracerEnable(false); } void Interface::connect(unsigned port, unsigned device) { @@ -341,38 +340,6 @@ void Interface::paletteUpdate(PaletteMode mode) { video.generate_palette(mode); } -bool Interface::tracerEnable(bool trace) { - string pathname = {path(group(ID::ROM)), "debug/"}; - if(trace == true) directory::create(pathname); - - if(trace == true && !tracer.open()) { - for(unsigned n = 0; n <= 999; n++) { - string filename = {pathname, "trace-", format<3, '0'>(n), ".log"}; - if(file::exists(filename)) continue; - tracer.open(filename, file::mode::write); - return true; - } - } - - if(trace == false && tracer.open()) { - tracer.close(); - return true; - } - - return false; -} - -void Interface::exportMemory() { - string pathname = {path(group(ID::ROM)), "debug/"}; - directory::create(pathname); - - file::write({pathname, "work.ram"}, cpu.wram, 128 * 1024); - file::write({pathname, "video.ram"}, ppu.vram, 64 * 1024); - file::write({pathname, "sprite.ram"}, ppu.oam, 544); - file::write({pathname, "palette.ram"}, ppu.cgram, 512); - file::write({pathname, "apu.ram"}, smp.apuram, 64 * 1024); -} - Interface::Interface() { interface = this; system.init(); diff --git a/sfc/interface/interface.hpp b/sfc/interface/interface.hpp index 8494ef63..e4f0f6dc 100644 --- a/sfc/interface/interface.hpp +++ b/sfc/interface/interface.hpp @@ -117,13 +117,8 @@ struct Interface : Emulator::Interface { void paletteUpdate(PaletteMode mode); - //debugger functions - bool tracerEnable(bool); - void exportMemory(); - Interface(); - file tracer; vector device; }; diff --git a/target-higan/input/hotkeys.cpp b/target-higan/input/hotkeys.cpp index d73ab27a..0df72552 100644 --- a/target-higan/input/hotkeys.cpp +++ b/target-higan/input/hotkeys.cpp @@ -129,28 +129,6 @@ void InputManager::appendHotkeys() { }; } - { - auto hotkey = new HotkeyInput; - hotkey->name = "Toggle Tracer"; - hotkey->mapping = "None"; - - hotkey->press = [&] { - utility->tracerToggle(); - }; - } - - { - auto hotkey = new HotkeyInput; - hotkey->name = "Export Memory"; - hotkey->mapping = "None"; - - hotkey->press = [&] { - if(program->active == nullptr) return; - system().exportMemory(); - utility->showMessage("Memory exported"); - }; - } - Configuration::Node node; for(auto& hotkey : hotkeyMap) { node.append(hotkey->mapping, string{hotkey->name}.replace(" ", "")); diff --git a/target-higan/utility/utility.cpp b/target-higan/utility/utility.cpp index 460cf81e..2645092a 100644 --- a/target-higan/utility/utility.cpp +++ b/target-higan/utility/utility.cpp @@ -101,7 +101,6 @@ void Utility::load() { void Utility::unload() { if(program->active == nullptr) return; - if(tracerEnable) tracerToggle(); cheatEditor->save({pathname[0], "cheats.bml"}); stateManager->save({pathname[0], "higan/states.bsa"}, 1); @@ -139,16 +138,6 @@ void Utility::loadState(unsigned slot) { showMessage({"Loaded from slot ", slot}); } -void Utility::tracerToggle() { - if(program->active == nullptr) return; - tracerEnable = !tracerEnable; - bool result = system().tracerEnable(tracerEnable); - if( tracerEnable && result) return utility->showMessage("Tracer activated"); - if( tracerEnable && !result) return tracerEnable = false, utility->showMessage("Unable to activate tracer"); - if(!tracerEnable && result) return utility->showMessage("Tracer deactivated"); - if(!tracerEnable && !result) return utility->showMessage("Unable to deactivate tracer"); -} - void Utility::synchronizeDSP() { if(program->active == nullptr) return; @@ -323,8 +312,3 @@ string Utility::libraryPath() { if(path.endsWith("/") == false) path.append("/"); return path; } - -Utility::Utility() { - tracerEnable = false; - statusTime = 0; -} diff --git a/target-higan/utility/utility.hpp b/target-higan/utility/utility.hpp index 82490808..5b3fb92c 100644 --- a/target-higan/utility/utility.hpp +++ b/target-higan/utility/utility.hpp @@ -17,8 +17,6 @@ struct Utility { void saveState(unsigned slot); void loadState(unsigned slot); - void tracerToggle(); - void synchronizeDSP(); void synchronizeRuby(); void updatePalette(); @@ -32,16 +30,13 @@ struct Utility { string libraryPath(); - Utility(); - lstring path; lstring pathname; private: - bool tracerEnable; string statusText; string statusMessage; - time_t statusTime; + time_t statusTime = 0; }; extern Utility* utility; diff --git a/target-loki/debugger/debugger.cpp b/target-loki/debugger/debugger.cpp index 3fb2ede8..f1947680 100644 --- a/target-loki/debugger/debugger.cpp +++ b/target-loki/debugger/debugger.cpp @@ -20,37 +20,30 @@ Debugger::Debugger() { void Debugger::load() { directory::create({interface->pathname, "loki/"}); - usageCPU = new uint8[0x1000000](); - usageAPU = new uint8[0x10000](); + cpuUsage = new uint8[0x1000000](); + apuUsage = new uint8[0x10000](); file fp; - if(fp.open({interface->pathname, "loki/usage.cpu.bin"}, file::mode::read)) { - if(fp.size() == 0x1000000) fp.read(usageCPU, 0x1000000); + if(fp.open({interface->pathname, "loki/cpu.usage.map"}, file::mode::read)) { + if(fp.size() == 0x1000000) fp.read(cpuUsage, 0x1000000); fp.close(); } - if(fp.open({interface->pathname, "loki/usage.apu.bin"}, file::mode::read)) { - if(fp.size() == 0x10000) fp.read(usageAPU, 0x10000); + if(fp.open({interface->pathname, "loki/apu.usage.map"}, file::mode::read)) { + if(fp.size() == 0x10000) fp.read(apuUsage, 0x10000); fp.close(); } } void Debugger::unload() { - if(tracerFile.open()) tracerFile.close(); - - file fp; - if(fp.open({interface->pathname, "loki/usage.cpu.bin"}, file::mode::write)) { - fp.write(usageCPU, 0x1000000); - fp.close(); - } - if(fp.open({interface->pathname, "loki/usage.apu.bin"}, file::mode::write)) { - fp.write(usageAPU, 0x10000); - fp.close(); - } - delete[] usageCPU; - delete[] usageAPU; - usageCPU = nullptr; - usageAPU = nullptr; + if(cpuTracerFile.open()) cpuTracerFile.close(); + if(smpTracerFile.open()) smpTracerFile.close(); + file::write({interface->pathname, "loki/cpu.usage.map"}, cpuUsage, 0x1000000); + file::write({interface->pathname, "loki/apu.usage.map"}, apuUsage, 0x10000); + delete[] cpuUsage; + delete[] apuUsage; + cpuUsage = nullptr; + apuUsage = nullptr; } void Debugger::main() { @@ -68,10 +61,14 @@ void Debugger::run() { void Debugger::stop() { running = false; - cpuRunFor.reset(); - cpuRunTo.reset(); - cpuStepFor.reset(); - cpuStepTo.reset(); + cpuRunFor = nothing; + cpuRunTo = nothing; + cpuStepFor = nothing; + cpuStepTo = nothing; + smpRunFor = nothing; + smpRunTo = nothing; + smpStepFor = nothing; + smpStepTo = nothing; } void Debugger::leave() { @@ -86,10 +83,11 @@ bool Debugger::breakpointTest(Source source, Breakpoint::Mode mode, unsigned add if(bp.mode != mode) continue; if(bp.addr != addr) continue; if(bp.mode != Breakpoint::Mode::Execute && bp.data && bp.data() != data) continue; - echo("Breakpoint #", n, " hit"); - if(bp.mode == Breakpoint::Mode::Read ) echo("; read ", hex<2>(data)); - if(bp.mode == Breakpoint::Mode::Write) echo("; wrote ", hex<2>(data)); - echo("; triggered: ", ++bp.triggered, "\n"); + string output = {"Breakpoint #", n, " hit"}; + if(bp.mode == Breakpoint::Mode::Read ) output.append("; read ", hex<2>(data)); + if(bp.mode == Breakpoint::Mode::Write) output.append("; wrote ", hex<2>(data)); + output.append("; triggered: ", ++bp.triggered); + echo(output, "\n"); return true; } return false; @@ -98,28 +96,30 @@ bool Debugger::breakpointTest(Source source, Breakpoint::Mode mode, unsigned add string Debugger::cpuDisassemble() { char text[4096]; SFC::cpu.disassemble_opcode(text); - return {text, " I:", (unsigned)SFC::cpu.field(), " V:", format<3>(SFC::cpu.vcounter()), " H:", format<4>(SFC::cpu.hcounter())}; + return {text, " F:", (unsigned)SFC::cpu.field(), " V:", format<3>(SFC::cpu.vcounter()), " H:", format<4>(SFC::cpu.hcounter())}; } string Debugger::cpuDisassemble(unsigned addr, bool e, bool m, bool x) { char text[4096]; SFC::cpu.disassemble_opcode(text, addr, e, m, x); - return {text, " I:", (unsigned)SFC::cpu.field(), " V:", format<3>(SFC::cpu.vcounter()), " H:", format<4>(SFC::cpu.hcounter())}; + return {text, " F:", (unsigned)SFC::cpu.field(), " V:", format<3>(SFC::cpu.vcounter()), " H:", format<4>(SFC::cpu.hcounter())}; } void Debugger::cpuExec(uint24 addr) { - usageCPU[addr] |= Usage::Execute; - if(SFC::cpu.regs.e == 0) usageCPU[addr] &= ~Usage::FlagE; - if(SFC::cpu.regs.p.m == 0) usageCPU[addr] &= ~Usage::FlagM; - if(SFC::cpu.regs.p.x == 0) usageCPU[addr] &= ~Usage::FlagX; - if(SFC::cpu.regs.e == 1) usageCPU[addr] |= Usage::FlagE; - if(SFC::cpu.regs.p.m == 1) usageCPU[addr] |= Usage::FlagM; - if(SFC::cpu.regs.p.x == 1) usageCPU[addr] |= Usage::FlagX; + cpuUsage[addr] |= Usage::Execute; + if(SFC::cpu.regs.e == 0) cpuUsage[addr] &= ~Usage::FlagE; + if(SFC::cpu.regs.p.m == 0) cpuUsage[addr] &= ~Usage::FlagM; + if(SFC::cpu.regs.p.x == 0) cpuUsage[addr] &= ~Usage::FlagX; + if(SFC::cpu.regs.e == 1) cpuUsage[addr] |= Usage::FlagE; + if(SFC::cpu.regs.p.m == 1) cpuUsage[addr] |= Usage::FlagM; + if(SFC::cpu.regs.p.x == 1) cpuUsage[addr] |= Usage::FlagX; - if(tracerFile.open()) { - if(!tracerMask || tracerMask[addr] == false) { - if(tracerMask) tracerMask[addr] = true; - tracerFile.print(cpuDisassemble(), "\n"); + cpuInstructionCounter++; + + if(cpuTracerFile.open()) { + if(!cpuTracerMask || cpuTracerMask[addr] == false) { + if(cpuTracerMask) cpuTracerMask[addr] = true; + cpuTracerFile.print(cpuDisassemble(), "\n"); } } @@ -154,12 +154,12 @@ void Debugger::cpuExec(uint24 addr) { } void Debugger::cpuRead(uint24 addr, uint8 data) { - usageCPU[addr] |= Usage::Read; + cpuUsage[addr] |= Usage::Read; if(breakpointTest(Source::CPU, Breakpoint::Mode::Read, addr, data)) leave(); } void Debugger::cpuWrite(uint24 addr, uint8 data) { - usageCPU[addr] |= Usage::Write; + cpuUsage[addr] |= Usage::Write; if(breakpointTest(Source::CPU, Breakpoint::Mode::Write, addr, data)) leave(); } @@ -182,21 +182,30 @@ void Debugger::echoBreakpoints() { } } -void Debugger::echoDisassemble(unsigned addr, signed size) { - if(!(usageCPU[addr] & Usage::Execute)) return echo("No usage data available for cpu/", hex<6>(addr), "\n"); +void Debugger::echoDisassemble(Source source, unsigned addr, signed size) { + if(source != Source::CPU && source != Source::SMP) return; + const unsigned maximumDisplacement = (source == Source::CPU ? 5 : 4); //maximum opcode length + uint8* usage = (source == Source::CPU ? cpuUsage : apuUsage); + if(!(usage[addr] & Usage::Execute)) return echo("No usage data available for ", sourceName(source), "/", hex<6>(addr), "\n"); while(size > 0) { - string text = cpuDisassemble(addr, usageCPU[addr] & Usage::FlagE, usageCPU[addr] & Usage::FlagM, usageCPU[addr] & Usage::FlagX); + string text; + if(source == Source::CPU) { + text = cpuDisassemble(addr, usage[addr] & Usage::FlagE, usage[addr] & Usage::FlagM, usage[addr] & Usage::FlagX); + } + if(source == Source::SMP) { + text = smpDisassemble(addr, usage[addr] & Usage::FlagP); + } text.resize(20); //remove register information echo(text, "\n"); if(--size <= 0) break; unsigned displacement = 1; - while(displacement < 5) { //maximum opcode length is four bytes - if(usageCPU[addr + displacement] & Usage::Execute) break; + while(displacement < maximumDisplacement) { //maximum opcode length is four bytes + if(usage[addr + displacement] & Usage::Execute) break; displacement++; } - if(displacement >= 5) { + if(displacement >= maximumDisplacement) { echo("...\n"); return; } @@ -205,6 +214,7 @@ void Debugger::echoDisassemble(unsigned addr, signed size) { } void Debugger::echoHex(Source source, unsigned addr, signed size) { + if(memorySize(source) == 0) return; //not a valid memory pool while(size > 0) { string hexdata, asciidata; for(unsigned n = 0; n < 16; n++) { @@ -245,6 +255,10 @@ uint8 Debugger::memoryRead(Source source, unsigned addr) { return SFC::smp.apuram[addr & 0xffff]; } + if(source == Source::WRAM) { + return SFC::cpu.wram[addr & 0x1ffff]; + } + if(source == Source::VRAM) { return SFC::ppu.vram[addr & 0xffff]; } @@ -264,11 +278,12 @@ unsigned Debugger::memorySize(Source source) { switch(source) { case Source::CPU: return 0x1000000; case Source::APU: return 0x10000; + case Source::WRAM: return 0x20000; case Source::VRAM: return 0x10000; case Source::OAM: return 544; case Source::CGRAM: return 512; } - return 1; + return 0; } void Debugger::memoryWrite(Source source, unsigned addr, uint8 data) { @@ -282,6 +297,11 @@ void Debugger::memoryWrite(Source source, unsigned addr, uint8 data) { return; } + if(source == Source::WRAM) { + SFC::cpu.wram[addr & 0x1ffff] = data; + return; + } + if(source == Source::VRAM) { SFC::ppu.vram[addr & 0xffff] = data; return; @@ -324,22 +344,66 @@ void Debugger::ppuVramWrite(uint16 addr, uint8 data) { if(breakpointTest(Source::VRAM, Breakpoint::Mode::Write, addr, data)) leave(); } +string Debugger::smpDisassemble() { + return SFC::smp.disassemble_opcode(SFC::smp.regs.pc, SFC::smp.regs.p.p); +} + +string Debugger::smpDisassemble(uint16 addr, bool p) { + return SFC::smp.disassemble_opcode(addr, p); +} + void Debugger::smpExec(uint16 addr) { - usageAPU[addr] |= Usage::Execute; + apuUsage[addr] |= Usage::Execute; + if(SFC::smp.regs.p.p == 0) apuUsage[addr] &= ~Usage::FlagP; + if(SFC::smp.regs.p.p == 1) apuUsage[addr] |= Usage::FlagP; + + smpInstructionCounter++; + + if(smpTracerFile.open()) { + if(!smpTracerMask || smpTracerMask[addr] == false) { + if(smpTracerMask) smpTracerMask[addr] = true; + smpTracerFile.print(smpDisassemble(), "\n"); + } + } if(breakpointTest(Source::SMP, Breakpoint::Mode::Execute, addr)) { - leave(); + echo(smpDisassemble(), "\n"); + return leave(); + } + + if(smpRunFor) { + if(--smpRunFor() == 0) { + echo(smpDisassemble(), "\n"); + return leave(); + } + } + + if(smpRunTo) { + if(addr == smpRunTo()) { + echo(smpDisassemble(), "\n"); + return leave(); + } + } + + if(smpStepFor) { + echo(smpDisassemble(), "\n"); + if(--smpStepFor() == 0) return leave(); + } + + if(smpStepTo) { + echo(smpDisassemble(), "\n"); + if(addr == smpStepTo()) return leave(); } } void Debugger::smpRead(uint16 addr, uint8 data) { - usageAPU[addr] |= Usage::Read; + apuUsage[addr] |= Usage::Read; if(breakpointTest(Source::SMP, Breakpoint::Mode::Read, addr, data)) leave(); if(breakpointTest(Source::APU, Breakpoint::Mode::Read, addr, data)) leave(); } void Debugger::smpWrite(uint16 addr, uint8 data) { - usageAPU[addr] |= Usage::Write; + apuUsage[addr] |= Usage::Write; if(breakpointTest(Source::SMP, Breakpoint::Mode::Write, addr, data)) leave(); if(breakpointTest(Source::APU, Breakpoint::Mode::Write, addr, data)) leave(); } @@ -351,9 +415,43 @@ string Debugger::sourceName(Source source) { case Source::PPU: return "ppu"; case Source::DSP: return "dsp"; case Source::APU: return "apu"; + case Source::WRAM: return "wram"; case Source::VRAM: return "vram"; case Source::OAM: return "oam"; case Source::CGRAM: return "cgram"; } return "none"; } + +void Debugger::tracerDisable(Source source) { + if(source != Source::CPU && source != Source::SMP) return; + file& tracerFile = (source == Source::CPU ? cpuTracerFile : smpTracerFile); + if(tracerFile.open() == false) return; + tracerFile.close(); + echo(sourceName(source).upper(), " tracer disabled\n"); +} + +void Debugger::tracerEnable(Source source, string filename) { + if(source != Source::CPU && source != Source::SMP) return; + file& tracerFile = (source == Source::CPU ? cpuTracerFile : smpTracerFile); + if(tracerFile.open() == true) return; + if(tracerFile.open(filename, file::mode::write)) { + echo(sourceName(source).upper(), " tracer enabled\n"); + } +} + +void Debugger::tracerMaskDisable(Source source) { + if(source != Source::CPU && source != Source::SMP) return; + bitvector& tracerMask = (source == Source::CPU ? cpuTracerMask : smpTracerMask); + tracerMask.reset(); + echo(sourceName(source).upper(), " tracer mask disabled\n"); +} + +void Debugger::tracerMaskEnable(Source source) { + if(source != Source::CPU && source != Source::SMP) return; + bitvector& tracerMask = (source == Source::CPU ? cpuTracerMask : smpTracerMask); + unsigned size = (source == Source::CPU ? 0x1000000 : 0x10000); + tracerMask.resize(size); + tracerMask.clear(); + echo(sourceName(source).upper(), " tracer mask enabled\n"); +} diff --git a/target-loki/debugger/debugger.hpp b/target-loki/debugger/debugger.hpp index 7138e9e2..647b2993 100644 --- a/target-loki/debugger/debugger.hpp +++ b/target-loki/debugger/debugger.hpp @@ -1,11 +1,11 @@ struct Debugger { - enum class Source : unsigned { CPU, SMP, PPU, DSP, APU, VRAM, OAM, CGRAM }; + enum class Source : unsigned { CPU, SMP, PPU, DSP, APU, WRAM, VRAM, OAM, CGRAM }; struct Breakpoint { Source source = Source::CPU; enum class Mode : unsigned { Disabled, Read, Write, Execute } mode = Mode::Disabled; unsigned addr = 0; - optional data = false; + maybe data; unsigned triggered = 0; //counter for number of times breakpoint was hit }; @@ -19,8 +19,9 @@ struct Debugger { FlagM = 0x10, FlagX = 0x20, //APU - DspRead = 0x08, - DspWrite = 0x10, + FlagP = 0x08, + DspRead = 0x10, + DspWrite = 0x20, }; }; @@ -41,7 +42,7 @@ struct Debugger { void cpuRead(uint24 addr, uint8 data); void cpuWrite(uint24 addr, uint8 data); void echoBreakpoints(); - void echoDisassemble(unsigned addr, signed size); + void echoDisassemble(Source source, unsigned addr, signed size); void echoHex(Source source, unsigned addr, signed size); void memoryExport(Source source, string filename); uint8 memoryRead(Source source, unsigned addr); @@ -53,22 +54,36 @@ struct Debugger { void ppuOamWrite(uint16 addr, uint8 data); void ppuVramRead(uint16 addr, uint8 data); void ppuVramWrite(uint16 addr, uint8 data); + string smpDisassemble(); + string smpDisassemble(uint16 addr, bool p); void smpExec(uint16 addr); void smpRead(uint16 addr, uint8 data); void smpWrite(uint16 addr, uint8 data); string sourceName(Source source); + void tracerDisable(Source source); + void tracerEnable(Source source, string filename); + void tracerMaskDisable(Source source); + void tracerMaskEnable(Source source); bool running = false; + uint8* apuUsage = nullptr; vector breakpoints; - optional cpuRunFor = false; - optional cpuRunTo = false; - optional cpuStepFor = false; - optional cpuStepTo = false; - file tracerFile; - bitvector tracerMask; - uint8* usageCPU = nullptr; - uint8* usageAPU = nullptr; + unsigned cpuInstructionCounter = 0; + maybe cpuRunFor; + maybe cpuRunTo; + maybe cpuStepFor; + maybe cpuStepTo; + file cpuTracerFile; + bitvector cpuTracerMask; + uint8* cpuUsage = nullptr; + unsigned smpInstructionCounter = 0; + maybe smpRunFor; + maybe smpRunTo; + maybe smpStepFor; + maybe smpStepTo; + file smpTracerFile; + bitvector smpTracerMask; }; extern Debugger* debugger; diff --git a/target-loki/terminal/terminal.cpp b/target-loki/terminal/terminal.cpp index 31087629..c77f4d00 100644 --- a/target-loki/terminal/terminal.cpp +++ b/target-loki/terminal/terminal.cpp @@ -24,6 +24,7 @@ void Terminal::command(string t) { if(t.beginsWith("ppu/" )) { source = Debugger::Source::PPU; t.ltrim<1>("ppu/" ); } if(t.beginsWith("dsp/" )) { source = Debugger::Source::DSP; t.ltrim<1>("dsp/" ); } if(t.beginsWith("apu/" )) { source = Debugger::Source::APU; t.ltrim<1>("apu/" ); } + if(t.beginsWith("wram/" )) { source = Debugger::Source::WRAM; t.ltrim<1>("wram/" ); } if(t.beginsWith("vram/" )) { source = Debugger::Source::VRAM; t.ltrim<1>("vram/" ); } if(t.beginsWith("oam/" )) { source = Debugger::Source::OAM; t.ltrim<1>("oam/" ); } if(t.beginsWith("cgram/")) { source = Debugger::Source::CGRAM; t.ltrim<1>("cgram/"); } @@ -56,7 +57,7 @@ void Terminal::command(string t) { if(args[0] == "write" ) bp.mode = Debugger::Breakpoint::Mode::Write; if(args[0] == "execute") bp.mode = Debugger::Breakpoint::Mode::Execute; bp.addr = hex(args[1]); - if(argc >= 3) bp.data = {true, (uint8_t)hex(args[2])}; + if(argc >= 3) bp.data = (uint8_t)hex(args[2]); debugger->breakpoints.append(bp); debugger->echoBreakpoints(); return; @@ -81,13 +82,25 @@ void Terminal::command(string t) { return; } + if(s == "counter") { + if(source == Debugger::Source::CPU) echo("CPU instructions executed: ", debugger->cpuInstructionCounter, "\n"); + if(source == Debugger::Source::SMP) echo("SMP instructions executed: ", debugger->smpInstructionCounter, "\n"); + return; + } + + if(s == "counter.reset") { + if(source == Debugger::Source::CPU) { echo("CPU instruction counter reset\n"); debugger->cpuInstructionCounter = 0; } + if(source == Debugger::Source::SMP) { echo("SMP instruction counter reset\n"); debugger->smpInstructionCounter = 0; } + return; + } + if(s == "disassemble" && argc >= 1 && argc <= 2) { - debugger->echoDisassemble(hex(args[0]), argc == 2 ? decimal(args[1]) : 16); + debugger->echoDisassemble(source, hex(args[0]), argc == 2 ? decimal(args[1]) : 16); return; } if(s == "export" && argc <= 1) { - string filename = {debugger->sourceName(source), "-", string::datetime().transform(" :", "--"), ".bin"}; + string filename = {debugger->sourceName(source), "-", string::datetime().transform(" :", "--"), ".ram"}; if(argc >= 1) filename = args[0]; string pathname = {interface->pathname, "loki/", filename}; debugger->memoryExport(source, pathname); @@ -118,68 +131,65 @@ void Terminal::command(string t) { if(s == "run.for" && argc == 1) { debugger->run(); - debugger->cpuRunFor = {true, (unsigned)decimal(args[0])}; + if(source == Debugger::Source::CPU) debugger->cpuRunFor = (unsigned)decimal(args[0]); + if(source == Debugger::Source::SMP) debugger->smpRunFor = (unsigned)decimal(args[0]); return; } if(s == "run.to" && argc == 1) { debugger->run(); - debugger->cpuRunTo = {true, (unsigned)hex(args[0])}; + if(source == Debugger::Source::CPU) debugger->cpuRunTo = (unsigned)hex(args[0]); + if(source == Debugger::Source::SMP) debugger->smpRunTo = (unsigned)hex(args[0]); return; } if(s == "step" && argc == 0) { debugger->run(); - debugger->cpuStepFor = {true, 1u}; + if(source == Debugger::Source::CPU) debugger->cpuStepFor = 1u; + if(source == Debugger::Source::SMP) debugger->smpStepFor = 1u; return; } if(s == "step.for" && argc == 1) { debugger->run(); - debugger->cpuStepFor = {true, (unsigned)decimal(args[0])}; + if(source == Debugger::Source::CPU) debugger->cpuStepFor = (unsigned)decimal(args[0]); + if(source == Debugger::Source::SMP) debugger->smpStepFor = (unsigned)decimal(args[0]); return; } if(s == "step.to" && argc == 1) { debugger->run(); - debugger->cpuStepTo = {true, (unsigned)hex(args[0])}; + if(source == Debugger::Source::CPU) debugger->cpuStepTo = (unsigned)hex(args[0]); + if(source == Debugger::Source::SMP) debugger->smpStepTo = (unsigned)hex(args[0]); return; } if(s == "tracer.enable" && argc <= 1) { - if(debugger->tracerFile.open() == false) { - string filename = {"trace-", string::datetime().transform(" :", "--"), ".log"}; - if(argc >= 1) filename = args[0]; - string pathname = {interface->pathname, "loki/", filename}; - if(debugger->tracerFile.open(pathname, file::mode::write)) { - echo("Tracer enabled\n"); - } - } + string filename = {debugger->sourceName(source), "-trace-", string::datetime().transform(" :", "--"), ".log"}; + if(argc >= 1) filename = args[0]; + string pathname = {interface->pathname, "loki/", filename}; + debugger->tracerEnable(source, pathname); return; } if(s == "tracer.disable") { - if(debugger->tracerFile.open() == true) { - debugger->tracerFile.close(); - echo("Tracer disabled\n"); - } + debugger->tracerDisable(source); return; } - if(s == "tracer.mask" && argc == 1) { - if(args[0] != "false") { - debugger->tracerMask.resize(0x1000000); - debugger->tracerMask.clear(); - echo("Tracer mask enabled\n"); - } else { - debugger->tracerMask.reset(); - echo("Tracer mask disabled\n"); - } + if(s == "tracer.mask.enable") { + debugger->tracerMaskEnable(source); + return; + } + + if(s == "tracer.mask.disable") { + debugger->tracerMaskDisable(source); return; } if(s == "usage.reset") { - memset(debugger->usageCPU, 0, 0x1000000); + if(source == Debugger::Source::CPU) memset(debugger->cpuUsage, 0x00, 0x1000000); + if(source == Debugger::Source::APU) memset(debugger->apuUsage, 0x00, 0x10000); return; }