mirror of https://github.com/bsnes-emu/bsnes.git
Update to v099r05 release.
byuu says: Changelog: - added nall/vfs - converted Famicom core to use nall/vfs interface instead of nall/stream interface
This commit is contained in:
parent
40abcfc4a5
commit
f04d9d58f5
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <nall/nall.hpp>
|
||||
#include <nall/vfs.hpp>
|
||||
using namespace nall;
|
||||
|
||||
#include <audio/audio.hpp>
|
||||
|
@ -9,7 +10,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "099.04";
|
||||
static const string Version = "099.05";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
|
|
@ -46,6 +46,8 @@ struct Interface {
|
|||
vector<Port> ports;
|
||||
|
||||
struct Bind {
|
||||
virtual auto path(uint) -> string { return ""; }
|
||||
virtual auto open(uint, string, vfs::file::mode, bool) -> vfs::shared::file { return {}; }
|
||||
virtual auto loadRequest(uint, string, string, bool) -> void {}
|
||||
virtual auto loadRequest(uint, string, bool) -> void {}
|
||||
virtual auto saveRequest(uint, string) -> void {}
|
||||
|
@ -54,12 +56,13 @@ struct Interface {
|
|||
virtual auto inputPoll(uint, uint, uint) -> int16 { return 0; }
|
||||
virtual auto inputRumble(uint, uint, uint, bool) -> void {}
|
||||
virtual auto dipSettings(const Markup::Node&) -> uint { return 0; }
|
||||
virtual auto path(uint) -> string { return ""; }
|
||||
virtual auto notify(string text) -> void { print(text, "\n"); }
|
||||
};
|
||||
Bind* bind = nullptr;
|
||||
|
||||
//callback bindings (provided by user interface)
|
||||
auto path(uint id) -> string { return bind->path(id); }
|
||||
auto open(uint id, string name, vfs::file::mode mode, bool required = false) -> vfs::shared::file { return bind->open(id, name, mode, required); }
|
||||
auto loadRequest(uint id, string name, string type, bool required) -> void { return bind->loadRequest(id, name, type, required); }
|
||||
auto loadRequest(uint id, string path, bool required) -> void { return bind->loadRequest(id, path, required); }
|
||||
auto saveRequest(uint id, string path) -> void { return bind->saveRequest(id, path); }
|
||||
|
@ -68,7 +71,6 @@ struct Interface {
|
|||
auto inputPoll(uint port, uint device, uint input) -> int16 { return bind->inputPoll(port, device, input); }
|
||||
auto inputRumble(uint port, uint device, uint input, bool enable) -> void { return bind->inputRumble(port, device, input, enable); }
|
||||
auto dipSettings(const Markup::Node& node) -> uint { return bind->dipSettings(node); }
|
||||
auto path(uint group) -> string { return bind->path(group); }
|
||||
template<typename... P> auto notify(P&&... p) -> void { return bind->notify({forward<P>(p)...}); }
|
||||
|
||||
//information
|
||||
|
@ -86,7 +88,7 @@ struct Interface {
|
|||
//media interface
|
||||
virtual auto loaded() -> bool { return false; }
|
||||
virtual auto sha256() -> string { return ""; }
|
||||
virtual auto group(uint id) -> uint = 0;
|
||||
virtual auto group(uint id) -> uint { return 0; }
|
||||
virtual auto load(uint id) -> void {}
|
||||
virtual auto save() -> void {}
|
||||
virtual auto load(uint id, const stream& memory) -> void {}
|
||||
|
|
|
@ -41,18 +41,45 @@ Board::Board(Markup::Node& document) {
|
|||
if(chrrom.size) chrrom.data = new uint8_t[chrrom.size]();
|
||||
if(chrram.size) chrram.data = new uint8_t[chrram.size]();
|
||||
|
||||
if(auto name = prom["name"].text()) interface->loadRequest(ID::ProgramROM, name, true);
|
||||
if(auto name = pram["name"].text()) interface->loadRequest(ID::ProgramRAM, name, false);
|
||||
if(auto name = crom["name"].text()) interface->loadRequest(ID::CharacterROM, name, true);
|
||||
if(auto name = cram["name"].text()) interface->loadRequest(ID::CharacterRAM, name, false);
|
||||
|
||||
if(auto name = pram["name"].text()) Famicom::cartridge.memory.append({ID::ProgramRAM, name});
|
||||
if(auto name = cram["name"].text()) Famicom::cartridge.memory.append({ID::CharacterRAM, name});
|
||||
if(prgrom.name = prom["name"].text()) {
|
||||
if(auto fp = interface->open(ID::Famicom, prgrom.name, vfs::file::mode::read, true)) {
|
||||
fp->read(prgrom.data, min(prgrom.size, fp->size()));
|
||||
}
|
||||
}
|
||||
if(prgram.name = pram["name"].text()) {
|
||||
if(auto fp = interface->open(ID::Famicom, prgram.name, vfs::file::mode::read)) {
|
||||
fp->read(prgram.data, min(prgram.size, fp->size()));
|
||||
}
|
||||
}
|
||||
if(chrrom.name = crom["name"].text()) {
|
||||
if(auto fp = interface->open(ID::Famicom, chrrom.name, vfs::file::mode::read, true)) {
|
||||
fp->read(chrrom.data, min(chrrom.size, fp->size()));
|
||||
}
|
||||
}
|
||||
if(chrram.name = cram["name"].text()) {
|
||||
if(auto fp = interface->open(ID::Famicom, chrram.name, vfs::file::mode::read)) {
|
||||
fp->read(chrram.data, min(chrram.size, fp->size()));
|
||||
}
|
||||
}
|
||||
|
||||
prgram.writable = true;
|
||||
chrram.writable = true;
|
||||
}
|
||||
|
||||
auto Board::save() -> void {
|
||||
if(auto name = prgram.name) {
|
||||
if(auto fp = interface->open(ID::Famicom, name, vfs::file::mode::write)) {
|
||||
fp->write(prgram.data, prgram.size);
|
||||
}
|
||||
}
|
||||
|
||||
if(auto name = chrram.name) {
|
||||
if(auto fp = interface->open(ID::Famicom, name, vfs::file::mode::write)) {
|
||||
fp->write(chrram.data, chrram.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto Board::Memory::read(uint addr) const -> uint8 {
|
||||
return data[mirror(addr, size)];
|
||||
}
|
||||
|
|
|
@ -7,16 +7,19 @@ struct Board {
|
|||
inline auto read(uint addr) const -> uint8;
|
||||
inline auto write(uint addr, uint8 data) -> void;
|
||||
|
||||
uint8_t* data;
|
||||
uint size;
|
||||
bool writable;
|
||||
string name;
|
||||
uint8_t* data = nullptr;
|
||||
uint size = 0;
|
||||
bool writable = false;
|
||||
};
|
||||
|
||||
Board(Markup::Node& document);
|
||||
virtual ~Board() = default;
|
||||
|
||||
static auto mirror(uint addr, uint size) -> uint;
|
||||
|
||||
Board(Markup::Node& document);
|
||||
auto save() -> void;
|
||||
|
||||
virtual auto main() -> void;
|
||||
virtual auto tick() -> void;
|
||||
|
||||
|
|
|
@ -26,20 +26,30 @@ auto Cartridge::main() -> void {
|
|||
board->main();
|
||||
}
|
||||
|
||||
auto Cartridge::load() -> void {
|
||||
interface->loadRequest(ID::Manifest, "manifest.bml", true);
|
||||
auto Cartridge::load() -> bool {
|
||||
if(auto fp = interface->open(ID::Famicom, "manifest.bml", vfs::file::mode::read, true)) {
|
||||
fp->reads(information.markup);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
Board::load(information.markup); //this call will set Cartridge::board if successful
|
||||
if(!board) return;
|
||||
if(!board) return false;
|
||||
|
||||
Hash::SHA256 sha;
|
||||
sha.data(board->prgrom.data, board->prgrom.size);
|
||||
sha.data(board->chrrom.data, board->chrrom.size);
|
||||
_sha256 = sha.digest();
|
||||
return true;
|
||||
}
|
||||
|
||||
auto Cartridge::save() -> void {
|
||||
board->save();
|
||||
}
|
||||
|
||||
auto Cartridge::unload() -> void {
|
||||
memory.reset();
|
||||
delete board;
|
||||
board = nullptr;
|
||||
}
|
||||
|
||||
auto Cartridge::power() -> void {
|
||||
|
|
|
@ -9,7 +9,8 @@ struct Cartridge : Thread {
|
|||
auto manifest() const -> string;
|
||||
auto title() const -> string;
|
||||
|
||||
auto load() -> void;
|
||||
auto load() -> bool;
|
||||
auto save() -> void;
|
||||
auto unload() -> void;
|
||||
|
||||
auto power() -> void;
|
||||
|
@ -22,12 +23,6 @@ struct Cartridge : Thread {
|
|||
string title;
|
||||
} information;
|
||||
|
||||
struct Memory {
|
||||
unsigned id;
|
||||
string name;
|
||||
};
|
||||
vector<Memory> memory;
|
||||
|
||||
//privileged:
|
||||
Board* board = nullptr;
|
||||
string _sha256;
|
||||
|
|
|
@ -128,65 +128,12 @@ auto Interface::sha256() -> string {
|
|||
return cartridge.sha256();
|
||||
}
|
||||
|
||||
auto Interface::group(uint id) -> uint {
|
||||
switch(id) {
|
||||
case ID::SystemManifest:
|
||||
return 0;
|
||||
case ID::Manifest:
|
||||
case ID::ProgramROM:
|
||||
case ID::ProgramRAM:
|
||||
case ID::CharacterROM:
|
||||
case ID::CharacterRAM:
|
||||
return 1;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
auto Interface::load(uint id) -> void {
|
||||
system.load();
|
||||
}
|
||||
|
||||
auto Interface::save() -> void {
|
||||
for(auto& memory : cartridge.memory) {
|
||||
saveRequest(memory.id, memory.name);
|
||||
}
|
||||
}
|
||||
|
||||
auto Interface::load(uint id, const stream& stream) -> void {
|
||||
if(id == ID::SystemManifest) {
|
||||
system.information.manifest = stream.text();
|
||||
}
|
||||
|
||||
if(id == ID::Manifest) {
|
||||
cartridge.information.markup = stream.text();
|
||||
}
|
||||
|
||||
if(id == ID::ProgramROM) {
|
||||
stream.read(cartridge.board->prgrom.data, min(cartridge.board->prgrom.size, stream.size()));
|
||||
}
|
||||
|
||||
if(id == ID::ProgramRAM) {
|
||||
stream.read(cartridge.board->prgram.data, min(cartridge.board->prgram.size, stream.size()));
|
||||
}
|
||||
|
||||
if(id == ID::CharacterROM) {
|
||||
stream.read(cartridge.board->chrrom.data, min(cartridge.board->chrrom.size, stream.size()));
|
||||
}
|
||||
|
||||
if(id == ID::CharacterRAM) {
|
||||
stream.read(cartridge.board->chrram.data, min(cartridge.board->chrram.size, stream.size()));
|
||||
}
|
||||
}
|
||||
|
||||
auto Interface::save(uint id, const stream& stream) -> void {
|
||||
if(id == ID::ProgramRAM) {
|
||||
stream.write(cartridge.board->prgram.data, cartridge.board->prgram.size);
|
||||
}
|
||||
|
||||
if(id == ID::CharacterRAM) {
|
||||
stream.write(cartridge.board->chrram.data, cartridge.board->chrram.size);
|
||||
}
|
||||
system.save();
|
||||
}
|
||||
|
||||
auto Interface::unload() -> void {
|
||||
|
|
|
@ -1,21 +1,11 @@
|
|||
namespace Famicom {
|
||||
|
||||
struct ID {
|
||||
enum : uint {
|
||||
enum : uint { //paths
|
||||
System,
|
||||
Famicom,
|
||||
};
|
||||
|
||||
enum : uint {
|
||||
SystemManifest,
|
||||
|
||||
Manifest,
|
||||
ProgramROM,
|
||||
ProgramRAM,
|
||||
CharacterROM,
|
||||
CharacterRAM,
|
||||
};
|
||||
|
||||
enum : uint { //bitmasks
|
||||
ControllerPort1 = 1,
|
||||
ControllerPort2 = 2,
|
||||
|
@ -35,11 +25,8 @@ struct Interface : Emulator::Interface {
|
|||
|
||||
auto loaded() -> bool;
|
||||
auto sha256() -> string;
|
||||
auto group(uint id) -> uint;
|
||||
auto load(uint id) -> void;
|
||||
auto save() -> void;
|
||||
auto load(uint id, const stream& stream) -> void;
|
||||
auto save(uint id, const stream& stream) -> void;
|
||||
auto unload() -> void;
|
||||
|
||||
auto connect(uint port, uint device) -> void;
|
||||
|
|
|
@ -21,12 +21,20 @@ auto System::runToSave() -> void {
|
|||
}
|
||||
}
|
||||
|
||||
auto System::load() -> void {
|
||||
interface->loadRequest(ID::SystemManifest, "manifest.bml", true);
|
||||
auto System::load() -> bool {
|
||||
if(auto fp = interface->open(ID::System, "manifest.bml", vfs::file::mode::read, true)) {
|
||||
fp->reads(information.manifest);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
auto document = BML::unserialize(information.manifest);
|
||||
cartridge.load();
|
||||
serializeInit();
|
||||
_loaded = true;
|
||||
return _loaded = true;
|
||||
}
|
||||
|
||||
auto System::save() -> void {
|
||||
cartridge.save();
|
||||
}
|
||||
|
||||
auto System::unload() -> void {
|
||||
|
|
|
@ -6,7 +6,8 @@ struct System {
|
|||
auto run() -> void;
|
||||
auto runToSave() -> void;
|
||||
|
||||
auto load() -> void;
|
||||
auto load() -> bool;
|
||||
auto save() -> void;
|
||||
auto unload() -> void;
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
auto Program::path(uint id) -> string {
|
||||
return mediumPaths(id);
|
||||
}
|
||||
|
||||
auto Program::open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file {
|
||||
if(auto result = vfs::fs::file::open({path(id), name}, mode)) return result;
|
||||
if(name == "manifest.bml") {
|
||||
if(auto manifest = execute("icarus", "--manifest", path(id))) {
|
||||
return vfs::memory::file::open(manifest.output.data<uint8_t>(), manifest.output.size());
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
//request from emulation core to load non-volatile media folder
|
||||
auto Program::loadRequest(uint id, string name, string type, bool required) -> void {
|
||||
string location = BrowserDialog()
|
||||
|
@ -116,9 +130,5 @@ auto Program::dipSettings(const Markup::Node& node) -> uint {
|
|||
return 0;
|
||||
}
|
||||
|
||||
auto Program::path(uint group) -> string {
|
||||
return mediumPaths(group);
|
||||
}
|
||||
|
||||
auto Program::notify(string text) -> void {
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ struct Program : Emulator::Interface::Bind {
|
|||
auto quit() -> void;
|
||||
|
||||
//interface.cpp
|
||||
auto path(uint id) -> string override;
|
||||
auto open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file override;
|
||||
auto loadRequest(uint id, string name, string type, bool required) -> void override;
|
||||
auto loadRequest(uint id, string path, bool required) -> void override;
|
||||
auto saveRequest(uint id, string path) -> void override;
|
||||
|
@ -14,7 +16,6 @@ struct Program : Emulator::Interface::Bind {
|
|||
auto inputPoll(uint port, uint device, uint input) -> int16 override;
|
||||
auto inputRumble(uint port, uint device, uint input, bool enable) -> void override;
|
||||
auto dipSettings(const Markup::Node& node) -> uint override;
|
||||
auto path(uint group) -> string override;
|
||||
auto notify(string text) -> void override;
|
||||
|
||||
//medium.cpp
|
||||
|
|
|
@ -239,7 +239,7 @@ struct file : inode, varint {
|
|||
#endif
|
||||
}
|
||||
|
||||
auto end() -> bool {
|
||||
auto end() const -> bool {
|
||||
if(!fp) return true; //file not open
|
||||
return file_offset >= file_size;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
#include <nall/vfs/vfs.hpp>
|
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
|
||||
#include <nall/file.hpp>
|
||||
|
||||
namespace nall { namespace vfs { namespace fs {
|
||||
|
||||
struct file : vfs::file {
|
||||
static auto open(string location_, mode mode_) -> vfs::shared::file {
|
||||
auto instance = shared_pointer<file>{new file};
|
||||
if(!instance->_open(location_, mode_)) return {};
|
||||
return instance;
|
||||
}
|
||||
|
||||
auto size() const -> uintmax override {
|
||||
return _fp.size();
|
||||
}
|
||||
|
||||
auto offset() const -> uintmax override {
|
||||
return _fp.offset();
|
||||
}
|
||||
|
||||
auto seek(intmax offset_, index index_) -> void override {
|
||||
_fp.seek(offset_, (nall::file::index)index_);
|
||||
}
|
||||
|
||||
auto read() -> uint8_t override {
|
||||
return _fp.read();
|
||||
}
|
||||
|
||||
auto write(uint8_t data_) -> void override {
|
||||
_fp.write(data_);
|
||||
}
|
||||
|
||||
auto flush() -> void override {
|
||||
_fp.flush();
|
||||
}
|
||||
|
||||
private:
|
||||
file() = default;
|
||||
file(const file&) = delete;
|
||||
auto operator=(const file&) -> file& = delete;
|
||||
|
||||
auto _open(string location_, mode mode_) -> bool {
|
||||
if(!_fp.open(location_, (nall::file::mode)mode_)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
nall::file _fp;
|
||||
};
|
||||
|
||||
}}}
|
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
|
||||
namespace nall { namespace vfs { namespace memory {
|
||||
|
||||
struct file : vfs::file {
|
||||
~file() { delete[] _data; }
|
||||
|
||||
static auto open(const uint8_t* data, uintmax size) -> vfs::shared::file {
|
||||
auto instance = shared_pointer<file>{new file};
|
||||
instance->_open(data, size);
|
||||
return instance;
|
||||
}
|
||||
|
||||
auto size() const -> uintmax override { return _size; }
|
||||
auto offset() const -> uintmax override { return _offset; }
|
||||
|
||||
auto seek(intmax offset, index mode) -> void override {
|
||||
if(mode == index::absolute) _offset = (uintmax)offset;
|
||||
if(mode == index::relative) _offset += (intmax)offset;
|
||||
}
|
||||
|
||||
auto read() -> uint8_t override {
|
||||
if(_offset >= _size) return 0x00;
|
||||
return _data[_offset++];
|
||||
}
|
||||
|
||||
auto write(uint8_t data) -> void override {
|
||||
if(_offset >= _size) return;
|
||||
_data[_offset++] = data;
|
||||
}
|
||||
|
||||
private:
|
||||
file() = default;
|
||||
file(const file&) = delete;
|
||||
auto operator=(const file&) -> file& = delete;
|
||||
|
||||
auto _open(const uint8_t* data, uintmax size) -> void {
|
||||
_size = size;
|
||||
_data = new uint8_t[size];
|
||||
nall::memory::copy(_data, data, size);
|
||||
}
|
||||
|
||||
uint8_t* _data = nullptr;
|
||||
uintmax _size = 0;
|
||||
uintmax _offset = 0;
|
||||
};
|
||||
|
||||
}}}
|
|
@ -0,0 +1,71 @@
|
|||
#pragma once
|
||||
|
||||
#include <nall/range.hpp>
|
||||
#include <nall/shared-pointer.hpp>
|
||||
|
||||
namespace nall { namespace vfs {
|
||||
|
||||
struct file {
|
||||
enum class mode : uint { read, write, modify, create };
|
||||
enum class index : uint { absolute, relative };
|
||||
|
||||
virtual ~file() = default;
|
||||
|
||||
virtual auto size() const -> uintmax = 0;
|
||||
virtual auto offset() const -> uintmax = 0;
|
||||
|
||||
virtual auto seek(intmax offset, index = index::absolute) -> void = 0;
|
||||
virtual auto read() -> uint8_t = 0;
|
||||
virtual auto write(uint8_t data) -> void = 0;
|
||||
virtual auto flush() -> void {}
|
||||
|
||||
auto end() const -> bool {
|
||||
return offset() >= size();
|
||||
}
|
||||
|
||||
auto read(uint8_t* data, uintmax bytes) -> void {
|
||||
while(bytes--) *data++ = read();
|
||||
}
|
||||
|
||||
auto readl(uint bytes) -> uintmax {
|
||||
uintmax data = 0;
|
||||
for(auto n : range(bytes)) data |= (uintmax)read() << n * 8;
|
||||
return data;
|
||||
}
|
||||
|
||||
auto readm(uint bytes) -> uintmax {
|
||||
uintmax data = 0;
|
||||
for(auto n : range(bytes)) data = data << 8 | read();
|
||||
return data;
|
||||
}
|
||||
|
||||
auto reads(string& s) -> void {
|
||||
s.resize(size());
|
||||
read(s.get<uint8_t>(), s.size());
|
||||
}
|
||||
|
||||
auto write(const uint8_t* data, uintmax bytes) -> void {
|
||||
while(bytes--) write(*data++);
|
||||
}
|
||||
|
||||
auto writel(uintmax data, uint bytes) -> void {
|
||||
for(auto n : range(bytes)) write(data), data >>= 8;
|
||||
}
|
||||
|
||||
auto writem(uintmax data, uint bytes) -> void {
|
||||
for(auto n : rrange(bytes)) write(data >> n * 8);
|
||||
}
|
||||
|
||||
auto writes(const string& s) -> void {
|
||||
write(s.data<uint8_t>(), s.size());
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
namespace nall { namespace vfs { namespace shared {
|
||||
using file = shared_pointer<vfs::file>;
|
||||
}}}
|
||||
|
||||
#include <nall/vfs/fs/file.hpp>
|
||||
#include <nall/vfs/memory/file.hpp>
|
Loading…
Reference in New Issue