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:
Tim Allen 2016-06-20 21:00:32 +10:00
parent 40abcfc4a5
commit f04d9d58f5
17 changed files with 269 additions and 104 deletions

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <nall/nall.hpp> #include <nall/nall.hpp>
#include <nall/vfs.hpp>
using namespace nall; using namespace nall;
#include <audio/audio.hpp> #include <audio/audio.hpp>
@ -9,7 +10,7 @@ using namespace nall;
namespace Emulator { namespace Emulator {
static const string Name = "higan"; 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 Author = "byuu";
static const string License = "GPLv3"; static const string License = "GPLv3";
static const string Website = "http://byuu.org/"; static const string Website = "http://byuu.org/";

View File

@ -46,6 +46,8 @@ struct Interface {
vector<Port> ports; vector<Port> ports;
struct Bind { 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, string, bool) -> void {}
virtual auto loadRequest(uint, string, bool) -> void {} virtual auto loadRequest(uint, string, bool) -> void {}
virtual auto saveRequest(uint, string) -> void {} virtual auto saveRequest(uint, string) -> void {}
@ -54,12 +56,13 @@ struct Interface {
virtual auto inputPoll(uint, uint, uint) -> int16 { return 0; } virtual auto inputPoll(uint, uint, uint) -> int16 { return 0; }
virtual auto inputRumble(uint, uint, uint, bool) -> void {} virtual auto inputRumble(uint, uint, uint, bool) -> void {}
virtual auto dipSettings(const Markup::Node&) -> uint { return 0; } virtual auto dipSettings(const Markup::Node&) -> uint { return 0; }
virtual auto path(uint) -> string { return ""; }
virtual auto notify(string text) -> void { print(text, "\n"); } virtual auto notify(string text) -> void { print(text, "\n"); }
}; };
Bind* bind = nullptr; Bind* bind = nullptr;
//callback bindings (provided by user interface) //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 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 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); } 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 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 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 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)...}); } template<typename... P> auto notify(P&&... p) -> void { return bind->notify({forward<P>(p)...}); }
//information //information
@ -86,7 +88,7 @@ struct Interface {
//media interface //media interface
virtual auto loaded() -> bool { return false; } virtual auto loaded() -> bool { return false; }
virtual auto sha256() -> string { return ""; } 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 load(uint id) -> void {}
virtual auto save() -> void {} virtual auto save() -> void {}
virtual auto load(uint id, const stream& memory) -> void {} virtual auto load(uint id, const stream& memory) -> void {}

View File

@ -41,18 +41,45 @@ Board::Board(Markup::Node& document) {
if(chrrom.size) chrrom.data = new uint8_t[chrrom.size](); if(chrrom.size) chrrom.data = new uint8_t[chrrom.size]();
if(chrram.size) chrram.data = new uint8_t[chrram.size](); if(chrram.size) chrram.data = new uint8_t[chrram.size]();
if(auto name = prom["name"].text()) interface->loadRequest(ID::ProgramROM, name, true); if(prgrom.name = prom["name"].text()) {
if(auto name = pram["name"].text()) interface->loadRequest(ID::ProgramRAM, name, false); if(auto fp = interface->open(ID::Famicom, prgrom.name, vfs::file::mode::read, true)) {
if(auto name = crom["name"].text()) interface->loadRequest(ID::CharacterROM, name, true); fp->read(prgrom.data, min(prgrom.size, fp->size()));
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(prgram.name = pram["name"].text()) {
if(auto name = cram["name"].text()) Famicom::cartridge.memory.append({ID::CharacterRAM, name}); 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; prgram.writable = true;
chrram.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 { auto Board::Memory::read(uint addr) const -> uint8 {
return data[mirror(addr, size)]; return data[mirror(addr, size)];
} }

View File

@ -7,16 +7,19 @@ struct Board {
inline auto read(uint addr) const -> uint8; inline auto read(uint addr) const -> uint8;
inline auto write(uint addr, uint8 data) -> void; inline auto write(uint addr, uint8 data) -> void;
uint8_t* data; string name;
uint size; uint8_t* data = nullptr;
bool writable; uint size = 0;
bool writable = false;
}; };
Board(Markup::Node& document);
virtual ~Board() = default; virtual ~Board() = default;
static auto mirror(uint addr, uint size) -> uint; static auto mirror(uint addr, uint size) -> uint;
Board(Markup::Node& document);
auto save() -> void;
virtual auto main() -> void; virtual auto main() -> void;
virtual auto tick() -> void; virtual auto tick() -> void;

View File

@ -26,20 +26,30 @@ auto Cartridge::main() -> void {
board->main(); board->main();
} }
auto Cartridge::load() -> void { auto Cartridge::load() -> bool {
interface->loadRequest(ID::Manifest, "manifest.bml", true); 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 Board::load(information.markup); //this call will set Cartridge::board if successful
if(!board) return; if(!board) return false;
Hash::SHA256 sha; Hash::SHA256 sha;
sha.data(board->prgrom.data, board->prgrom.size); sha.data(board->prgrom.data, board->prgrom.size);
sha.data(board->chrrom.data, board->chrrom.size); sha.data(board->chrrom.data, board->chrrom.size);
_sha256 = sha.digest(); _sha256 = sha.digest();
return true;
}
auto Cartridge::save() -> void {
board->save();
} }
auto Cartridge::unload() -> void { auto Cartridge::unload() -> void {
memory.reset(); delete board;
board = nullptr;
} }
auto Cartridge::power() -> void { auto Cartridge::power() -> void {

View File

@ -9,7 +9,8 @@ struct Cartridge : Thread {
auto manifest() const -> string; auto manifest() const -> string;
auto title() const -> string; auto title() const -> string;
auto load() -> void; auto load() -> bool;
auto save() -> void;
auto unload() -> void; auto unload() -> void;
auto power() -> void; auto power() -> void;
@ -22,12 +23,6 @@ struct Cartridge : Thread {
string title; string title;
} information; } information;
struct Memory {
unsigned id;
string name;
};
vector<Memory> memory;
//privileged: //privileged:
Board* board = nullptr; Board* board = nullptr;
string _sha256; string _sha256;

View File

@ -128,65 +128,12 @@ auto Interface::sha256() -> string {
return cartridge.sha256(); 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 { auto Interface::load(uint id) -> void {
system.load(); system.load();
} }
auto Interface::save() -> void { auto Interface::save() -> void {
for(auto& memory : cartridge.memory) { system.save();
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);
}
} }
auto Interface::unload() -> void { auto Interface::unload() -> void {

View File

@ -1,21 +1,11 @@
namespace Famicom { namespace Famicom {
struct ID { struct ID {
enum : uint { enum : uint { //paths
System, System,
Famicom, Famicom,
}; };
enum : uint {
SystemManifest,
Manifest,
ProgramROM,
ProgramRAM,
CharacterROM,
CharacterRAM,
};
enum : uint { //bitmasks enum : uint { //bitmasks
ControllerPort1 = 1, ControllerPort1 = 1,
ControllerPort2 = 2, ControllerPort2 = 2,
@ -35,11 +25,8 @@ struct Interface : Emulator::Interface {
auto loaded() -> bool; auto loaded() -> bool;
auto sha256() -> string; auto sha256() -> string;
auto group(uint id) -> uint;
auto load(uint id) -> void; auto load(uint id) -> void;
auto save() -> void; auto save() -> void;
auto load(uint id, const stream& stream) -> void;
auto save(uint id, const stream& stream) -> void;
auto unload() -> void; auto unload() -> void;
auto connect(uint port, uint device) -> void; auto connect(uint port, uint device) -> void;

View File

@ -21,12 +21,20 @@ auto System::runToSave() -> void {
} }
} }
auto System::load() -> void { auto System::load() -> bool {
interface->loadRequest(ID::SystemManifest, "manifest.bml", true); 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); auto document = BML::unserialize(information.manifest);
cartridge.load(); cartridge.load();
serializeInit(); serializeInit();
_loaded = true; return _loaded = true;
}
auto System::save() -> void {
cartridge.save();
} }
auto System::unload() -> void { auto System::unload() -> void {

View File

@ -6,7 +6,8 @@ struct System {
auto run() -> void; auto run() -> void;
auto runToSave() -> void; auto runToSave() -> void;
auto load() -> void; auto load() -> bool;
auto save() -> void;
auto unload() -> void; auto unload() -> void;
auto power() -> void; auto power() -> void;
auto reset() -> void; auto reset() -> void;

View File

@ -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 //request from emulation core to load non-volatile media folder
auto Program::loadRequest(uint id, string name, string type, bool required) -> void { auto Program::loadRequest(uint id, string name, string type, bool required) -> void {
string location = BrowserDialog() string location = BrowserDialog()
@ -116,9 +130,5 @@ auto Program::dipSettings(const Markup::Node& node) -> uint {
return 0; return 0;
} }
auto Program::path(uint group) -> string {
return mediumPaths(group);
}
auto Program::notify(string text) -> void { auto Program::notify(string text) -> void {
} }

View File

@ -6,6 +6,8 @@ struct Program : Emulator::Interface::Bind {
auto quit() -> void; auto quit() -> void;
//interface.cpp //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 name, string type, bool required) -> void override;
auto loadRequest(uint id, string path, bool required) -> void override; auto loadRequest(uint id, string path, bool required) -> void override;
auto saveRequest(uint id, string path) -> 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 inputPoll(uint port, uint device, uint input) -> int16 override;
auto inputRumble(uint port, uint device, uint input, bool enable) -> void override; auto inputRumble(uint port, uint device, uint input, bool enable) -> void override;
auto dipSettings(const Markup::Node& node) -> uint override; auto dipSettings(const Markup::Node& node) -> uint override;
auto path(uint group) -> string override;
auto notify(string text) -> void override; auto notify(string text) -> void override;
//medium.cpp //medium.cpp

View File

@ -239,7 +239,7 @@ struct file : inode, varint {
#endif #endif
} }
auto end() -> bool { auto end() const -> bool {
if(!fp) return true; //file not open if(!fp) return true; //file not open
return file_offset >= file_size; return file_offset >= file_size;
} }

3
nall/vfs.hpp Normal file
View File

@ -0,0 +1,3 @@
#pragma once
#include <nall/vfs/vfs.hpp>

51
nall/vfs/fs/file.hpp Normal file
View File

@ -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;
};
}}}

48
nall/vfs/memory/file.hpp Normal file
View File

@ -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;
};
}}}

71
nall/vfs/vfs.hpp Normal file
View File

@ -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>