forked from Lephenixnoir/fxos
86 lines
1.7 KiB
C++
86 lines
1.7 KiB
C++
#include "shell.h"
|
|
#include "parser.h"
|
|
#include "commands.h"
|
|
#include "theme.h"
|
|
|
|
#include <fmt/core.h>
|
|
|
|
using Selections = std::vector<std::pair<uint32_t,int>>;
|
|
|
|
static bool is_selected(uint32_t address, Selections const &sel)
|
|
{
|
|
for(auto &p: sel) {
|
|
if(address >= p.first && address < p.first + p.second) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void _h_hexdump(Session &session, Range r, Selections sel)
|
|
{
|
|
session.require_vspace();
|
|
VirtualSpace &v = *session.current_space;
|
|
|
|
uint32_t start = r.start & ~0xf;
|
|
uint32_t end = (r.end + 15) & ~0xf;
|
|
|
|
for(uint32_t pos = start; pos != end; pos += 16) {
|
|
fmt::print(theme(3), " 0x{:08x} ", pos);
|
|
|
|
/* Hexdump */
|
|
for(int offset = 0; offset < 16; offset++) {
|
|
if(!(offset % 4)) fmt::print(" ");
|
|
|
|
uint32_t addr = pos + offset;
|
|
if(addr < r.start || addr >= r.end) {
|
|
fmt::print(" ");
|
|
}
|
|
else if(is_selected(addr, sel)) {
|
|
fmt::print(theme(13), "{:02x}", v.read_u8(addr));
|
|
}
|
|
else {
|
|
fmt::print("{:02x}", v.read_u8(addr));
|
|
}
|
|
}
|
|
|
|
/* ASCII */
|
|
fmt::print(" ");
|
|
for(int offset = 0; offset < 16; offset++) {
|
|
if(!(offset % 4)) fmt::print(" ");
|
|
|
|
uint32_t addr = pos + offset;
|
|
if(addr < r.start || addr >= r.end) {
|
|
fmt::print(" ");
|
|
}
|
|
else {
|
|
int c = v.read_u8(addr);
|
|
fmt::print(theme(11), "{:c}", isprint(c) ? c : '.');
|
|
}
|
|
}
|
|
|
|
fmt::print("\n");
|
|
}
|
|
}
|
|
|
|
//---
|
|
// h
|
|
//---
|
|
|
|
static Range parse_h(Session &session, Parser &parser)
|
|
{
|
|
Range r = parser.range(session.current_space, 0, 128);
|
|
parser.end();
|
|
return r;
|
|
}
|
|
|
|
void _h(Session &session, Range r)
|
|
{
|
|
_h_hexdump(session, r, {});
|
|
}
|
|
|
|
[[gnu::constructor]] static void _(void)
|
|
{
|
|
shell_register_command("h",
|
|
[](Session &s, Parser &p){ _h(s, parse_h(s, p)); },
|
|
[](Session &s, Parser &p){ parse_h(s, p); });
|
|
}
|