diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp index 1349f888..2c0ee370 100644 --- a/emulator/emulator.hpp +++ b/emulator/emulator.hpp @@ -8,7 +8,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "094.37"; + static const string Version = "094.38"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/gba/apu/fifo.cpp b/gba/apu/fifo.cpp index 490f5bd0..17cf85ae 100644 --- a/gba/apu/fifo.cpp +++ b/gba/apu/fifo.cpp @@ -5,8 +5,8 @@ void APU::FIFO::read() { } void APU::FIFO::write(int8 byte) { - if(size == 32) return; - size++; + if(size == 32) rdoffset++; + else size++; sample[wroffset++] = byte; } diff --git a/gba/cartridge/cartridge.cpp b/gba/cartridge/cartridge.cpp index 39f699ff..815ef8c9 100644 --- a/gba/cartridge/cartridge.cpp +++ b/gba/cartridge/cartridge.cpp @@ -63,6 +63,11 @@ void Cartridge::load() { flashrom.size = info["size"].decimal(); for(unsigned n = 0; n < flashrom.size; n++) flashrom.data[n] = 0xff; + //if FlashROM ID not provided; guess that it's a Macronix chip + //this will not work for all games; in which case, the ID must be specified manually + if(!flashrom.id && flashrom.size == 64 * 1024) flashrom.id = 0x1cc2; + if(!flashrom.id && flashrom.size == 128 * 1024) flashrom.id = 0x09c2; + interface->loadRequest(ID::FlashROM, info["name"].text()); memory.append({ID::FlashROM, info["name"].text()}); } diff --git a/hiro/components.hpp b/hiro/components.hpp index e1a5a18d..6c03415d 100644 --- a/hiro/components.hpp +++ b/hiro/components.hpp @@ -50,22 +50,22 @@ #define Hiro_CheckButton #define Hiro_CheckLabel #define Hiro_ComboButton -#define Hiro_Console +//#define Hiro_Console #define Hiro_Frame #define Hiro_HexEdit #define Hiro_HorizontalScroller #define Hiro_HorizontalSlider -#define Hiro_IconView +//#define Hiro_IconView #define Hiro_Label #define Hiro_LineEdit #define Hiro_ListView #define Hiro_ProgressBar #define Hiro_RadioButton #define Hiro_RadioLabel -#define Hiro_SourceView +//#define Hiro_SourceView #define Hiro_TabFrame #define Hiro_TextEdit -#define Hiro_TreeView +//#define Hiro_TreeView #define Hiro_VerticalScroller #define Hiro_VerticalSlider #define Hiro_Viewport diff --git a/hiro/extension/browser-dialog.cpp b/hiro/extension/browser-dialog.cpp index b283493e..903ed8d6 100644 --- a/hiro/extension/browser-dialog.cpp +++ b/hiro/extension/browser-dialog.cpp @@ -13,17 +13,17 @@ struct BrowserDialogWindow { private: Window window; VerticalLayout layout{&window}; - HorizontalLayout pathLayout{&layout, Size{~0, 0}, 8}; + HorizontalLayout pathLayout{&layout, Size{~0, 0}, 5}; LineEdit pathName{&pathLayout, Size{~0, 0}, 0}; Button pathHome{&pathLayout, Size{0, 0}, 0}; Button pathRefresh{&pathLayout, Size{0, 0}, 0}; Button pathUp{&pathLayout, Size{0, 0}, 0}; - ListView view{&layout, Size{~0, ~0}, 8}; + ListView view{&layout, Size{~0, ~0}, 5}; HorizontalLayout controlLayout{&layout, Size{~0, 0}}; - ComboButton filterList{&controlLayout, Size{120, 0}, 8}; - LineEdit fileName{&controlLayout, Size{~0, 0}, 8}; - Button acceptButton{&controlLayout, Size{80, 0}, 8}; - Button cancelButton{&controlLayout, Size{80, 0}, 8}; + ComboButton filterList{&controlLayout, Size{120, 0}, 5}; + LineEdit fileName{&controlLayout, Size{~0, 0}, 5}; + Button acceptButton{&controlLayout, Size{80, 0}, 5}; + Button cancelButton{&controlLayout, Size{80, 0}, 5}; BrowserDialog::State& state; vector filters; @@ -116,7 +116,7 @@ auto BrowserDialogWindow::isMatch(const string& name) -> bool { auto BrowserDialogWindow::run() -> lstring { state.response.reset(); - layout.setMargin(8); + layout.setMargin(5); pathName.onActivate([&] { setPath(pathName.text()); }); pathHome.setBordered(false).setIcon(Icon::Go::Home).onActivate([&] { setPath(userpath()); }); pathRefresh.setBordered(false).setIcon(Icon::Action::Refresh).onActivate([&] { setPath(state.path); }); @@ -175,7 +175,7 @@ auto BrowserDialogWindow::setPath(string path) -> void { view.append(ListViewItem() .append(ListViewCell().setText(content).setIcon(Icon::Emblem::Folder)) - .append(ListViewCell().setText(octal(storage::mode({path, content}) & 0777, 3L))) + .append(ListViewCell().setText(octal(file_system_object::mode({path, content}) & 0777, 3L))) ); } @@ -186,7 +186,7 @@ auto BrowserDialogWindow::setPath(string path) -> void { view.append(ListViewItem() .append(ListViewCell().setText(content).setIcon(folderMode ? Icon::Action::Open : Icon::Emblem::File)) - .append(ListViewCell().setText(octal(storage::mode({path, content}) & 0777, 3L))) + .append(ListViewCell().setText(octal(file_system_object::mode({path, content}) & 0777, 3L))) ); } diff --git a/hiro/extension/message-dialog.cpp b/hiro/extension/message-dialog.cpp index 3f180dc0..2f1b5bde 100644 --- a/hiro/extension/message-dialog.cpp +++ b/hiro/extension/message-dialog.cpp @@ -46,24 +46,24 @@ auto MessageDialog::warning(const lstring& buttons) -> string { auto MessageDialog::_run() -> string { Window window; VerticalLayout layout{&window}; - HorizontalLayout messageLayout{&layout, Size{~0, 0}, 8}; - Canvas messageIcon{&messageLayout, Size{16, 16}, 8}; + HorizontalLayout messageLayout{&layout, Size{~0, 0}, 5}; + Canvas messageIcon{&messageLayout, Size{16, 16}, 5}; Label messageText{&messageLayout, Size{~0, 0}}; HorizontalLayout controlLayout{&layout, Size{~0, 0}}; Widget controlSpacer{&controlLayout, Size{~0, 0}}; - layout.setMargin(8); + layout.setMargin(5); messageIcon.setIcon(state.icon); messageText.setText(state.text); for(auto n : range(state.buttons)) { - Button button{&controlLayout, Size{80, 0}, 8}; + Button button{&controlLayout, Size{80, 0}, 5}; button.onActivate([&, n] { state.response = state.buttons[n]; window.setModal(false); }); button.setText(state.buttons[n]); button.setFocused(); //the last button will have effective focus } - signed widthMessage = 8 + 16 + 8 + Font::size(Font::sans(), state.text).width() + 8; - signed widthButtons = 8 + state.buttons.size() * 88; + signed widthMessage = 5 + 16 + 5 + Font::size(Font::sans(), state.text).width() + 5; + signed widthButtons = 5 + state.buttons.size() * 85; signed width = max(320, widthMessage, widthButtons); window.onClose([&] { window.setModal(false); }); diff --git a/nall/GNUmakefile b/nall/GNUmakefile index a24817bc..f2b6ee05 100644 --- a/nall/GNUmakefile +++ b/nall/GNUmakefile @@ -81,6 +81,14 @@ ifeq ($(platform),bsd) link += -Wl,-rpath=/usr/local/lib/gcc49 endif +# threading support +ifeq ($(threaded),true) + ifneq ($(filter $(platform),linux bsd),) + flags += -pthread + link += -lrt + endif +endif + # cross-compilation support ifeq ($(arch),x86) flags := -m32 $(flags) diff --git a/nall/any.hpp b/nall/any.hpp index cbdad800..9ee09fea 100644 --- a/nall/any.hpp +++ b/nall/any.hpp @@ -35,6 +35,11 @@ struct any { return static_cast::type>*>(container)->value; } + template auto get(const T& fallback) const -> const T& { + if(!is()) return fallback; + return static_cast::type>*>(container)->value; + } + template auto operator=(const T& value) -> any& { using auto_t = type_if, typename remove_extent::type>::type*, T>; diff --git a/nall/base64.hpp b/nall/base64.hpp deleted file mode 100644 index b3fb3707..00000000 --- a/nall/base64.hpp +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef NALL_BASE64_HPP -#define NALL_BASE64_HPP - -#include -#include -#include - -namespace nall { - -struct Base64 { - enum class Format : unsigned { MIME, URI }; - - inline static string encode(const uint8_t* data, unsigned size, Format format = Format::MIME); - inline static string encode(const vector& buffer, Format format = Format::MIME); - inline static string encode(const string& text, Format format = Format::MIME); - - inline static vector decode(const string& text); - -private: - inline static void table(char* data, Format format); - inline static uint8_t value(char data); -}; - -string Base64::encode(const uint8_t* data, unsigned size, Format format) { - vector result; - - char lookup[65]; - table(lookup, format); - - unsigned overflow = (3 - (size % 3)) % 3; //bytes to round to nearest multiple of 3 - uint8_t buffer; - - for(unsigned i = 0; i < size; i++) { - switch(i % 3) { - case 0: - buffer = data[i] >> 2; - result.append(lookup[buffer]); - buffer = (data[i] & 3) << 4; - result.append(lookup[buffer]); - break; - - case 1: - buffer |= data[i] >> 4; - result.last() = lookup[buffer]; - buffer = (data[i] & 15) << 2; - result.append(lookup[buffer]); - break; - - case 2: - buffer |= data[i] >> 6; - result.last() = lookup[buffer]; - buffer = (data[i] & 63); - result.append(lookup[buffer]); - break; - } - } - - if(lookup[64]) { - if(overflow >= 1) result.append(lookup[64]); - if(overflow >= 2) result.append(lookup[64]); - } - - return result; -} - -string Base64::encode(const vector& buffer, Format format) { - return encode(buffer.data(), buffer.size(), format); -} - -string Base64::encode(const string& text, Format format) { - return encode((const uint8_t*)text.data(), text.size(), format); -} - -vector Base64::decode(const string& text) { - vector result; - - uint8_t buffer, output; - for(unsigned i = 0; i < text.size(); i++) { - uint8_t buffer = value(text[i]); - if(buffer > 63) break; - - switch(i & 3) { - case 0: - output = buffer << 2; - break; - - case 1: - result.append(output | buffer >> 4); - output = (buffer & 15) << 4; - break; - - case 2: - result.append(output | buffer >> 2); - output = (buffer & 3) << 6; - break; - - case 3: - result.append(output | buffer); - break; - } - } - - return result; -} - -void Base64::table(char* data, Format format) { - for(unsigned n = 0; n < 26; n++) data[ 0 + n] = 'A' + n; - for(unsigned n = 0; n < 26; n++) data[26 + n] = 'a' + n; - for(unsigned n = 0; n < 10; n++) data[52 + n] = '0' + n; - - switch(format) { - case Format::MIME: - data[62] = '+'; - data[63] = '/'; - data[64] = '='; - break; - - case Format::URI: - data[62] = '-'; - data[63] = '_'; - data[64] = 0; - break; - } -} - -uint8_t Base64::value(char n) { - if(n >= 'A' && n <= 'Z') return n - 'A' + 0; - if(n >= 'a' && n <= 'z') return n - 'a' + 26; - if(n >= '0' && n <= '9') return n - '0' + 52; - if(n == '+' || n == '-') return 62; - if(n == '/' || n == '_') return 63; - return 64; //error code -} - -} - -#endif diff --git a/nall/beat/archive.hpp b/nall/beat/archive.hpp index c5a8f652..8b6d25a1 100644 --- a/nall/beat/archive.hpp +++ b/nall/beat/archive.hpp @@ -28,20 +28,26 @@ auto Archive::create(const string& beatname, const string& pathname, const strin scan(contents, pathname, pathname); for(auto& name : contents) { - if(name.endsWith("/")) { - name.rtrim("/"); - beat.writevu(0 | ((name.length() - 1) << 1)); - beat.writes(name); - } else { - File input{{pathname, name}, file::mode::read}; - if(!input) return false; + string location{pathname, name}; + bool directory = name.endsWith("/"); + bool readable = file_system_object::readable(location); + bool writable = file_system_object::writable(location); + bool executable = file_system_object::executable(location); + unsigned info = directory << 0 | readable << 1 | writable << 2 | executable << 3 | (name.rtrim("/").size() - 1) << 4; - beat.writevu(1 | ((name.length() - 1) << 1)); - beat.writes(name); + beat.writevu(info); + beat.writes(name); + if(directory) continue; + + File input{location, file::mode::read}; + if(input) { auto size = input.size(); beat.writevu(size); while(size--) beat.write(input.read()); beat.writel(input.checksum.value(), 4); + } else { + beat.writevu(0); + beat.writel(0x00000000, 4); } } @@ -61,14 +67,20 @@ auto Archive::unpack(const string& beatname, const string& pathname) -> bool { directory::create(pathname); while(beat.offset() < beat.size() - 4) { - auto data = beat.readvu(); - auto name = beat.reads((data >> 1) + 1); + auto info = beat.readvu(); + auto name = beat.reads((info >> 4) + 1); if(name.find("\\") || name.find("../")) return false; //block path exploits - if((data & 1) == 0) { - directory::create({pathname, name}); + string location{pathname, name}; + bool directory = info & 1; + bool readable = info & 2; + bool writable = info & 4; + bool executable = info & 8; + + if(directory) { + if(!nall::directory::create(location)) return false; } else { - File output{{pathname, name}, file::mode::write}; + File output{location, file::mode::write}; if(!output) return false; auto size = beat.readvu(); @@ -90,9 +102,10 @@ auto Archive::extract(const string& beatname, const string& filename) -> vector< beat.seek(beat.offset() + size); while(beat.offset() < beat.size() - 4) { - auto data = beat.readvu(); - auto name = beat.reads((data >> 1) + 1); - if((data & 1) == 0) continue; + auto info = beat.readvu(); + auto name = beat.reads((info >> 4) + 1); + if(info & 1) continue; //ignore directories + auto size = beat.readvu(); if(name != filename) { beat.seek(beat.offset() + size + 4); diff --git a/nall/beat/multi.hpp b/nall/beat/multi.hpp index a9e15796..62c4b113 100644 --- a/nall/beat/multi.hpp +++ b/nall/beat/multi.hpp @@ -222,7 +222,7 @@ protected: string readString(unsigned length) { string text; text.resize(length + 1); - char* p = text.pointer(); + char* p = text.get(); while(length--) *p++ = read(); return text; } diff --git a/nall/bitvector.hpp b/nall/bitvector.hpp index 24e9d8e4..9a6f16b1 100644 --- a/nall/bitvector.hpp +++ b/nall/bitvector.hpp @@ -1,6 +1,8 @@ #ifndef NALL_BITVECTOR_HPP #define NALL_BITVECTOR_HPP +#include + namespace nall { struct bitvector { diff --git a/nall/bmp.hpp b/nall/bmp.hpp deleted file mode 100644 index 6c39f13a..00000000 --- a/nall/bmp.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef NALL_BMP_HPP -#define NALL_BMP_HPP - -#include - -//BMP reader / writer -//note: only 24-bit RGB and 32-bit ARGB uncompressed images supported - -namespace nall { - -struct bmp { - inline static auto read(const string& filename, uint32_t*& data, unsigned& width, unsigned& height) -> bool; - inline static auto write(const string& filename, const uint32_t* data, unsigned width, unsigned height, unsigned pitch, bool alpha = false) -> bool; -}; - -auto bmp::read(const string& filename, uint32_t*& data, unsigned& width, unsigned& height) -> bool { - file fp; - if(fp.open(filename, file::mode::read) == false) return false; - if(fp.size() < 0x36) return false; - - if(fp.readm(2) != 0x424d) return false; - fp.seek(0x000a); - unsigned offset = fp.readl(4); - unsigned dibsize = fp.readl(4); - if(dibsize != 40) return false; - signed headerWidth = fp.readl(4); - if(headerWidth < 0) return false; - signed headerHeight = fp.readl(4); - fp.readl(2); - unsigned bitsPerPixel = fp.readl(2); - if(bitsPerPixel != 24 && bitsPerPixel != 32) return false; - unsigned compression = fp.readl(4); - if(compression != 0) return false; - fp.seek(offset); - - bool noFlip = headerHeight < 0; - width = headerWidth, height = abs(headerHeight); - data = new uint32_t[width * height]; - - unsigned bytesPerPixel = bitsPerPixel / 8; - unsigned alignedWidth = width * bytesPerPixel; - unsigned paddingLength = 0; - while(alignedWidth % 4) alignedWidth++, paddingLength++; - - for(unsigned y = 0; y < height; y++) { - uint32_t* p = noFlip ? data + y * width : data + (height - 1 - y) * width; - for(unsigned x = 0; x < width; x++, p++) { - *p = fp.readl(bytesPerPixel); - if(bytesPerPixel == 3) *p |= 255 << 24; - } - if(paddingLength) fp.readl(paddingLength); - } - - fp.close(); - return true; -} - -auto bmp::write(const string& filename, const uint32_t* data, unsigned width, unsigned height, unsigned pitch, bool alpha) -> bool { - file fp; - if(fp.open(filename, file::mode::write) == false) return false; - - unsigned bitsPerPixel = alpha ? 32 : 24; - unsigned bytesPerPixel = bitsPerPixel / 8; - unsigned alignedWidth = width * bytesPerPixel; - unsigned paddingLength = 0; - unsigned imageSize = alignedWidth * height; - unsigned fileSize = 0x36 + imageSize; - while(alignedWidth % 4) alignedWidth++, paddingLength++; - - fp.writem(0x424d, 2); //signature - fp.writel(fileSize, 4); //file size - fp.writel(0, 2); //reserved - fp.writel(0, 2); //reserved - fp.writel(0x36, 4); //offset - - fp.writel(40, 4); //DIB size - fp.writel(width, 4); //width - fp.writel(-height, 4); //height - fp.writel(1, 2); //color planes - fp.writel(bitsPerPixel, 2); //bits per pixel - fp.writel(0, 4); //compression method (BI_RGB) - fp.writel(imageSize, 4); //image data size - fp.writel(3780, 4); //horizontal resolution - fp.writel(3780, 4); //vertical resolution - fp.writel(0, 4); //palette size - fp.writel(0, 4); //important color count - - for(unsigned y = 0; y < height; y++) { - const uint32_t* p = (const uint32_t*)((const uint8_t*)data + y * pitch); - for(unsigned x = 0; x < width; x++) fp.writel(*p++, bytesPerPixel); - if(paddingLength) fp.writel(0, paddingLength); - } - - fp.close(); - return true; -} - -} - -#endif diff --git a/nall/database/odbc.hpp b/nall/database/odbc.hpp index 5abf2062..6ca51898 100644 --- a/nall/database/odbc.hpp +++ b/nall/database/odbc.hpp @@ -20,44 +20,61 @@ struct ODBC { auto operator=(Statement&& source) -> Statement& { _statement = source._statement; _output = source._output; + _values = move(source._values); source._statement = nullptr; source._output = 0; return *this; } + auto columns() -> unsigned { + SQLSMALLINT columns = 0; + if(statement()) SQLNumResultCols(statement(), &columns); + return columns; + } + auto integer(unsigned column) -> int64_t { + if(auto value = _values(column)) return value.get(0); int64_t value = 0; SQLGetData(statement(), 1 + column, SQL_C_SBIGINT, &value, 0, nullptr); + _values(column) = (int64_t)value; return value; } auto decimal(unsigned column) -> uint64_t { + if(auto value = _values(column)) return value.get(0); uint64_t value = 0; SQLGetData(statement(), 1 + column, SQL_C_UBIGINT, &value, 0, nullptr); + _values(column) = (uint64_t)value; return value; } auto real(unsigned column) -> double { + if(auto value = _values(column)) return value.get(0.0); double value = 0.0; SQLGetData(statement(), 1 + column, SQL_C_DOUBLE, &value, 0, nullptr); + _values(column) = (double)value; return value; } auto text(unsigned column) -> string { + if(auto value = _values(column)) return value.get({}); string value; value.resize(65535); SQLLEN size = 0; - SQLGetData(statement(), 1 + column, SQL_C_CHAR, value.pointer(), value.size(), &size); + SQLGetData(statement(), 1 + column, SQL_C_CHAR, value.get(), value.size(), &size); value.resize(size); + _values(column) = (string)value; return value; } auto data(unsigned column) -> vector { + if(auto value = _values(column)) return value.get>({}); vector value; value.resize(65535); SQLLEN size = 0; SQLGetData(statement(), 1 + column, SQL_C_CHAR, value.data(), value.size(), &size); value.resize(size); + _values(column) = (vector)value; return value; } @@ -72,6 +89,7 @@ struct ODBC { SQLHANDLE _statement = nullptr; unsigned _output = 0; + vector _values; //some ODBC drivers (eg MS-SQL) do not allow the same column to be read more than once }; struct Query : Statement { @@ -89,18 +107,23 @@ struct ODBC { } auto operator=(Query&& source) -> Query& { + Statement::operator=(move(source)); _bindings = move(source._bindings); - _statement = source._statement; _result = source._result; _input = source._input; _stepped = source._stepped; - source._statement = nullptr; source._result = SQL_SUCCESS; source._input = 0; source._stepped = false; return *this; } + explicit operator bool() { + //this is likely not the best way to test if the query has returned data ... + //but I wasn't able to find an ODBC API for this seemingly simple task + return statement() && success(); + } + //ODBC SQLBindParameter only holds pointers to data values //if the bound paramters go out of scope before the query is executed, binding would reference dangling pointers //so to work around this, we cache all parameters inside Query until the query is executed @@ -140,11 +163,13 @@ struct ODBC { } else if(binding.value.is()) { SQLBindParameter(_statement, 1 + binding.column, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &binding.value.get(), 0, nullptr); } else if(binding.value.is()) { + auto& value = binding.value.get(); SQLLEN length = SQL_NTS; - SQLBindParameter(_statement, 1 + binding.column, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 0, 0, (SQLPOINTER)binding.value.get().data(), 0, &length); + SQLBindParameter(_statement, 1 + binding.column, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, value.size(), 0, (SQLPOINTER)value.data(), 0, &length); } else if(binding.value.is>()) { - SQLLEN length = binding.value.get>().size(); - SQLBindParameter(_statement, 1 + binding.column, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARBINARY, 0, 0, (SQLPOINTER)binding.value.get>().data(), 0, &length); + auto& value = binding.value.get>(); + SQLLEN length = value.size(); + SQLBindParameter(_statement, 1 + binding.column, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARBINARY, value.size(), 0, (SQLPOINTER)value.data(), 0, &length); } } @@ -153,6 +178,7 @@ struct ODBC { if(!success()) return false; } + _values.reset(); //clear previous row's cached read results _result = SQLFetch(_statement); _output = 0; return success(); diff --git a/nall/database/sqlite3.hpp b/nall/database/sqlite3.hpp index 6e03e14d..aac2302f 100644 --- a/nall/database/sqlite3.hpp +++ b/nall/database/sqlite3.hpp @@ -31,6 +31,14 @@ struct SQLite3 { return *this; } + explicit operator bool() { + return sqlite3_data_count(statement()); + } + + auto columns() -> unsigned { + return sqlite3_column_count(statement()); + } + auto integer(unsigned column) -> int64_t { return sqlite3_column_int64(statement(), column); } @@ -47,7 +55,7 @@ struct SQLite3 { string result; if(auto text = sqlite3_column_text(statement(), column)) { result.resize(sqlite3_column_bytes(statement(), column)); - memory::copy(result.pointer(), text, result.size()); + memory::copy(result.get(), text, result.size()); } return result; } diff --git a/nall/decode/base64.hpp b/nall/decode/base64.hpp new file mode 100644 index 00000000..bbf1df36 --- /dev/null +++ b/nall/decode/base64.hpp @@ -0,0 +1,49 @@ +#ifndef NALL_DECODE_BASE64_HPP +#define NALL_DECODE_BASE64_HPP + +namespace nall { namespace Decode { + +inline auto Base64(const string& text) -> vector { + auto value = [](char n) -> uint8_t { + if(n >= 'A' && n <= 'Z') return n - 'A' + 0; + if(n >= 'a' && n <= 'z') return n - 'a' + 26; + if(n >= '0' && n <= '9') return n - '0' + 52; + if(n == '+' || n == '-') return 62; + if(n == '/' || n == '_') return 63; + return 64; //error code + }; + + vector result; + + uint8_t buffer, output; + for(unsigned i = 0; i < text.size(); i++) { + uint8_t buffer = value(text[i]); + if(buffer > 63) break; + + switch(i & 3) { + case 0: + output = buffer << 2; + break; + + case 1: + result.append(output | buffer >> 4); + output = (buffer & 15) << 4; + break; + + case 2: + result.append(output | buffer >> 2); + output = (buffer & 3) << 6; + break; + + case 3: + result.append(output | buffer); + break; + } + } + + return result; +} + +}} + +#endif diff --git a/nall/decode/bmp.hpp b/nall/decode/bmp.hpp index 04330639..2d7a0436 100644 --- a/nall/decode/bmp.hpp +++ b/nall/decode/bmp.hpp @@ -1,8 +1,79 @@ #ifndef NALL_DECODE_BMP_HPP #define NALL_DECODE_BMP_HPP -namespace nall { +namespace nall { namespace Decode { -} +struct BMP { + BMP() = default; + BMP(const string& filename) { load(filename); } + BMP(const uint8_t* data, unsigned size) { load(data, size); } + + explicit operator bool() const { return _data; } + + auto reset() -> void { + if(_data) { delete[] _data; _data = nullptr; } + } + + auto data() -> uint32_t* { return _data; } + auto data() const -> const uint32_t* { return _data; } + auto width() const -> unsigned { return _width; } + auto height() const -> unsigned { return _height; } + + auto load(const string& filename) -> bool { + auto buffer = file::read(filename); + return load(buffer.data(), buffer.size()); + } + + auto load(const uint8_t* data, unsigned size) -> bool { + if(size < 0x36) return false; + const uint8_t* p = data; + if(read(p, 2) != 0x4d42) return false; //signature + read(p, 8); + unsigned offset = read(p, 4); + if(read(p, 4) != 40) return false; //DIB size + signed width = read(p, 4); + if(width < 0) return false; + signed height = read(p, 4); + bool flip = height < 0; + if(flip) height = -height; + read(p, 2); + unsigned bitsPerPixel = read(p, 2); + if(bitsPerPixel != 24 && bitsPerPixel != 32) return false; + if(read(p, 4) != 0) return false; //compression type + + _width = width; + _height = height; + _data = new uint32_t[width * height]; + + unsigned bytesPerPixel = bitsPerPixel / 8; + unsigned alignedWidth = width * bytesPerPixel; + unsigned paddingLength = 0; + while(alignedWidth % 4) alignedWidth++, paddingLength++; + + p = data + offset; + for(auto y : range(height)) { + uint32_t* output = flip ? _data + (height - 1 - y) * width : _data + y * width; + for(auto x : range(width)) { + *output++ = read(p, bytesPerPixel) | (bitsPerPixel == 24 ? 255u << 24 : 0); + } + if(paddingLength) read(p, paddingLength); + } + + return true; + } + +private: + uint32_t* _data = nullptr; + unsigned _width = 0; + unsigned _height = 0; + + auto read(const uint8_t*& buffer, unsigned length) -> uintmax_t { + uintmax_t result = 0; + for(auto n : range(length)) result |= (uintmax_t)*buffer++ << (n << 3); + return result; + } +}; + +}} #endif diff --git a/nall/decode/png.hpp b/nall/decode/png.hpp index 3991f823..a8a61aee 100644 --- a/nall/decode/png.hpp +++ b/nall/decode/png.hpp @@ -31,8 +31,8 @@ struct PNG { uint8_t* data = nullptr; unsigned size = 0; - inline bool decode(const string& filename); - inline bool decode(const uint8_t* sourceData, unsigned sourceSize); + inline bool load(const string& filename); + inline bool load(const uint8_t* sourceData, unsigned sourceSize); inline unsigned readbits(const uint8_t*& data); unsigned bitpos = 0; @@ -54,14 +54,14 @@ protected: inline unsigned read(const uint8_t* data, unsigned length); }; -bool PNG::decode(const string& filename) { +bool PNG::load(const string& filename) { if(auto memory = file::read(filename)) { - return decode(memory.data(), memory.size()); + return load(memory.data(), memory.size()); } return false; } -bool PNG::decode(const uint8_t* sourceData, unsigned sourceSize) { +bool PNG::load(const uint8_t* sourceData, unsigned sourceSize) { if(sourceSize < 8) return false; if(read(sourceData + 0, 4) != 0x89504e47) return false; if(read(sourceData + 4, 4) != 0x0d0a1a0a) return false; diff --git a/nall/directory.hpp b/nall/directory.hpp index 1f19619e..ead023eb 100644 --- a/nall/directory.hpp +++ b/nall/directory.hpp @@ -2,9 +2,9 @@ #define NALL_DIRECTORY_HPP #include +#include #include #include -#include #include #include @@ -18,7 +18,7 @@ namespace nall { -struct directory : storage { +struct directory : file_system_object { static auto create(const string& pathname, unsigned permissions = 0755) -> bool; //recursive static auto remove(const string& pathname) -> bool; //recursive static auto exists(const string& pathname) -> bool; @@ -78,6 +78,7 @@ private: bool result = true; for(auto& part : list) { path.append(part, "/"); + if(directory::exists(path)) continue; result &= (_wmkdir(utf16_t(path)) == 0); } return result; diff --git a/nall/encode/base64.hpp b/nall/encode/base64.hpp new file mode 100644 index 00000000..fb130a34 --- /dev/null +++ b/nall/encode/base64.hpp @@ -0,0 +1,70 @@ +#ifndef NALL_ENCODE_BASE64_HPP +#define NALL_ENCODE_BASE64_HPP + +namespace nall { namespace Encode { + +inline auto Base64(const uint8_t* data, unsigned size, const string& format = "MIME") -> string { + vector result; + + char lookup[65]; + for(unsigned n = 0; n < 26; n++) lookup[ 0 + n] = 'A' + n; + for(unsigned n = 0; n < 26; n++) lookup[26 + n] = 'a' + n; + for(unsigned n = 0; n < 10; n++) lookup[52 + n] = '0' + n; + + if(format == "MIME") { + lookup[62] = '+'; + lookup[63] = '/'; + lookup[64] = '='; + } else if(format == "URI") { + lookup[62] = '-'; + lookup[63] = '_'; + lookup[64] = 0; + } else return ""; + + unsigned overflow = (3 - (size % 3)) % 3; //bytes to round to nearest multiple of 3 + uint8_t buffer; + + for(unsigned i = 0; i < size; i++) { + switch(i % 3) { + case 0: + buffer = data[i] >> 2; + result.append(lookup[buffer]); + buffer = (data[i] & 3) << 4; + result.append(lookup[buffer]); + break; + + case 1: + buffer |= data[i] >> 4; + result.last() = lookup[buffer]; + buffer = (data[i] & 15) << 2; + result.append(lookup[buffer]); + break; + + case 2: + buffer |= data[i] >> 6; + result.last() = lookup[buffer]; + buffer = (data[i] & 63); + result.append(lookup[buffer]); + break; + } + } + + if(lookup[64]) { + if(overflow >= 1) result.append(lookup[64]); + if(overflow >= 2) result.append(lookup[64]); + } + + return result; +} + +inline auto Base64(const vector& buffer, const string& format = "MIME") -> string { + return Base64(buffer.data(), buffer.size(), format); +} + +inline auto Base64(const string& text, const string& format = "MIME") -> string { + return Base64(text.binary(), text.size(), format); +} + +}} + +#endif diff --git a/nall/encode/bmp.hpp b/nall/encode/bmp.hpp new file mode 100644 index 00000000..7e22bbf5 --- /dev/null +++ b/nall/encode/bmp.hpp @@ -0,0 +1,49 @@ +#ifndef NALL_ENCODE_BMP_HPP +#define NALL_ENCODE_BMP_HPP + +namespace nall { namespace Encode { + +struct BMP { + static auto create(const string& filename, const uint32_t* data, unsigned width, unsigned height, bool alpha) -> bool { + file fp{filename, file::mode::write}; + if(!fp) return false; + + unsigned bitsPerPixel = alpha ? 32 : 24; + unsigned bytesPerPixel = bitsPerPixel / 8; + unsigned alignedWidth = width * bytesPerPixel; + unsigned paddingLength = 0; + unsigned imageSize = alignedWidth * height; + unsigned fileSize = 0x36 + imageSize; + while(alignedWidth % 4) alignedWidth++, paddingLength++; + + fp.writel(0x4d42, 2); //signature + fp.writel(fileSize, 4); //file size + fp.writel(0, 2); //reserved + fp.writel(0, 2); //reserved + fp.writel(0x36, 4); //offset + + fp.writel(40, 4); //DIB size + fp.writel(width, 4); //width + fp.writel(-height, 4); //height + fp.writel(1, 2); //color planes + fp.writel(bitsPerPixel, 2); //bits per pixel + fp.writel(0, 4); //compression method (BI_RGB) + fp.writel(imageSize, 4); //image data size + fp.writel(3780, 4); //horizontal resolution + fp.writel(3780, 4); //vertical resolution + fp.writel(0, 4); //palette size + fp.writel(0, 4); //important color count + + for(auto y : range(height)) { + const uint32_t* p = data + y * width; + for(auto x : range(width)) fp.writel(*p++, bytesPerPixel); + if(paddingLength) fp.writel(0, paddingLength); + } + + return true; + } +}; + +}} + +#endif diff --git a/nall/encode/zip.hpp b/nall/encode/zip.hpp index 4ea19020..a927ab5b 100644 --- a/nall/encode/zip.hpp +++ b/nall/encode/zip.hpp @@ -1,5 +1,5 @@ -#ifndef NALL_ZIP_HPP -#define NALL_ZIP_HPP +#ifndef NALL_ENCODE_ZIP_HPP +#define NALL_ENCODE_ZIP_HPP //creates uncompressed ZIP archives @@ -19,7 +19,7 @@ struct ZIP { //append path: append("path/"); //append file: append("path/file", data, size); - void append(string filename, const uint8_t* data = nullptr, unsigned size = 0u) { + auto append(string filename, const uint8_t* data = nullptr, unsigned size = 0u) -> void { filename.transform("\\", "/"); uint32_t checksum = Hash::CRC32(data, size).value(); directory.append({filename, checksum, size, fp.offset()}); diff --git a/nall/file-system-object.hpp b/nall/file-system-object.hpp new file mode 100644 index 00000000..f9114b56 --- /dev/null +++ b/nall/file-system-object.hpp @@ -0,0 +1,81 @@ +#ifndef NALL_STORAGE_HPP +#define NALL_STORAGE_HPP + +//generic abstraction layer for common storage operations against both files and directories +//these functions are not recursive; use directory::create() and directory::remove() for recursion + +#include +#include + +namespace nall { + +struct file_system_object { + enum class time : unsigned { access, modify }; + + static auto exists(const string& name) -> bool { + return access(name, F_OK) == 0; + } + + static auto readable(const string& name) -> bool { + return access(name, R_OK) == 0; + } + + static auto writable(const string& name) -> bool { + return access(name, W_OK) == 0; + } + + static auto executable(const string& name) -> bool { + return access(name, X_OK) == 0; + } + + static auto uid(const string& name) -> unsigned { + struct stat data{0}; + stat(name, &data); + return data.st_uid; + } + + static auto gid(const string& name) -> unsigned { + struct stat data{0}; + stat(name, &data); + return data.st_gid; + } + + static auto mode(const string& name) -> unsigned { + struct stat data{0}; + stat(name, &data); + return data.st_mode; + } + + static auto timestamp(const string& name, time mode = time::modify) -> time_t { + struct stat data = {0}; + stat(name, &data); + switch(mode) { default: + case time::access: return data.st_atime; + case time::modify: return data.st_mtime; + } + } + + //returns true if 'name' already exists + static auto create(const string& name, unsigned permissions = 0755) -> bool { + if(exists(name)) return true; + if(name.endsWith("/")) return mkdir(name, permissions) == 0; + int fd = open(name, O_CREAT | O_EXCL, permissions); + if(fd < 0) return false; + return close(fd), true; + } + + //returns false if 'name' and 'targetname' are on different file systems (requires copy) + static auto rename(const string& name, const string& targetname) -> bool { + return ::rename(name, targetname) == 0; + } + + //returns false if 'name' is a directory that is not empty + static auto remove(const string& name) -> bool { + if(name.endsWith("/")) return rmdir(name) == 0; + return unlink(name) == 0; + } +}; + +} + +#endif diff --git a/nall/file.hpp b/nall/file.hpp index 9bf15d9d..cddd1330 100644 --- a/nall/file.hpp +++ b/nall/file.hpp @@ -2,8 +2,8 @@ #define NALL_FILE_HPP #include +#include #include -#include #include #include #include @@ -12,7 +12,7 @@ namespace nall { -struct file : storage, varint { +struct file : file_system_object, varint { enum class mode : unsigned { read, write, modify, append, readwrite = modify, writeread = append }; enum class index : unsigned { absolute, relative }; @@ -37,25 +37,24 @@ struct file : storage, varint { } static auto truncate(const string& filename, unsigned size) -> bool { - #if !defined(_WIN32) + #if defined(API_POSIX) return truncate(filename, size) == 0; - #else - bool result = false; - FILE* fp = _wfopen(utf16_t(filename), L"rb+"); - if(fp) { - result = _chsize(fileno(fp), size) == 0; + #elif defined(API_WINDOWS) + if(auto fp = _wfopen(utf16_t(filename), L"rb+")) { + bool result = _chsize(fileno(fp), size) == 0; fclose(fp); + return result; } - return result; + return false; #endif } - //specialization of storage::exists(); returns false for folders + //returns false if specified filename is a directory static auto exists(const string& filename) -> bool { - #if !defined(_WIN32) + #if defined(API_POSIX) struct stat data; if(stat(filename, &data) != 0) return false; - #else + #elif defined(API_WINDOWS) struct __stat64 data; if(_wstat64(utf16_t(filename), &data) != 0) return false; #endif @@ -63,10 +62,10 @@ struct file : storage, varint { } static auto size(const string& filename) -> uintmax_t { - #if !defined(_WIN32) + #if defined(API_POSIX) struct stat data; stat(filename, &data); - #else + #elif defined(API_WINDOWS) struct __stat64 data; _wstat64(utf16_t(filename), &data); #endif @@ -240,9 +239,9 @@ struct file : storage, varint { auto truncate(unsigned size) -> bool { if(!fp) return false; //file not open - #if !defined(_WIN32) + #if defined(API_POSIX) return ftruncate(fileno(fp), size) == 0; - #else + #elif defined(API_WINDOWS) return _chsize(fileno(fp), size) == 0; #endif } @@ -264,12 +263,12 @@ struct file : storage, varint { if(fp) return false; switch(file_mode = mode_) { - #if !defined(_WIN32) + #if defined(API_POSIX) case mode::read: fp = fopen(filename, "rb" ); break; case mode::write: fp = fopen(filename, "wb+"); break; //need read permission for buffering case mode::readwrite: fp = fopen(filename, "rb+"); break; case mode::writeread: fp = fopen(filename, "wb+"); break; - #else + #elif defined(API_WINDOWS) case mode::read: fp = _wfopen(utf16_t(filename), L"rb" ); break; case mode::write: fp = _wfopen(utf16_t(filename), L"wb+"); break; case mode::readwrite: fp = _wfopen(utf16_t(filename), L"rb+"); break; diff --git a/nall/http/client.hpp b/nall/http/client.hpp index 9c578640..8a590fdc 100644 --- a/nall/http/client.hpp +++ b/nall/http/client.hpp @@ -3,21 +3,21 @@ #include -namespace nall { +namespace nall { namespace HTTP { -struct httpClient : httpRole { +struct Client : Role { inline auto open(const string& hostname, unsigned port = 80) -> bool; - inline auto upload(const httpRequest& request) -> bool; - inline auto download(const httpRequest& request) -> httpResponse; + inline auto upload(const Request& request) -> bool; + inline auto download(const Request& request) -> Response; inline auto close() -> void; - ~httpClient() { close(); } + ~Client() { close(); } private: signed fd = -1; addrinfo* info = nullptr; }; -auto httpClient::open(const string& hostname, unsigned port) -> bool { +auto Client::open(const string& hostname, unsigned port) -> bool { addrinfo hint = {0}; hint.ai_family = AF_UNSPEC; hint.ai_socktype = SOCK_STREAM; @@ -32,17 +32,17 @@ auto httpClient::open(const string& hostname, unsigned port) -> bool { return true; } -auto httpClient::upload(const httpRequest& request) -> bool { - return httpRole::upload(fd, request); +auto Client::upload(const Request& request) -> bool { + return Role::upload(fd, request); } -auto httpClient::download(const httpRequest& request) -> httpResponse { - httpResponse response(request); - httpRole::download(fd, response); +auto Client::download(const Request& request) -> Response { + Response response(request); + Role::download(fd, response); return response; } -auto httpClient::close() -> void { +auto Client::close() -> void { if(fd) { ::close(fd); fd = -1; @@ -54,6 +54,6 @@ auto httpClient::close() -> void { } } -} +}} #endif diff --git a/nall/http/message.hpp b/nall/http/message.hpp index 569a789e..b32f070e 100644 --- a/nall/http/message.hpp +++ b/nall/http/message.hpp @@ -4,32 +4,32 @@ //httpMessage: base class for httpRequest and httpResponse //provides shared functionality -namespace nall { +namespace nall { namespace HTTP { -struct httpVariable { +struct Variable { string name; string value; }; -struct httpVariables : vector { +struct Variables : vector { auto append(const string& name, const string& value) -> void; auto get(const string& name) const -> string; auto remove(const string& name) -> void; auto set(const string& name, const string& value) -> void; }; -auto httpVariables::append(const string& name, const string& value) -> void { +auto Variables::append(const string& name, const string& value) -> void { vector::append({name, value}); } -auto httpVariables::get(const string& name) const -> string { +auto Variables::get(const string& name) const -> string { for(auto& variable : *this) { if(variable.name.iequals(name)) return variable.value; } return ""; } -auto httpVariables::remove(const string& name) -> void { +auto Variables::remove(const string& name) -> void { while(true) { unsigned n = 0; bool found = false; @@ -43,7 +43,7 @@ auto httpVariables::remove(const string& name) -> void { } } -auto httpVariables::set(const string& name, const string& value) -> void { +auto Variables::set(const string& name, const string& value) -> void { for(auto& variable : *this) { if(!variable.name.iequals(name)) continue; variable.name = name; @@ -53,8 +53,8 @@ auto httpVariables::set(const string& name, const string& value) -> void { vector::append({name, value}); } -struct httpMessage { - using type = httpMessage; +struct Message { + using type = Message; virtual auto head(const function& callback) const -> bool = 0; virtual auto setHead() -> bool = 0; @@ -69,9 +69,9 @@ struct httpMessage { string _head; string _body; - httpVariables _header; + Variables _header; }; -} +}} #endif diff --git a/nall/http/request.hpp b/nall/http/request.hpp index a21676ea..186956c6 100644 --- a/nall/http/request.hpp +++ b/nall/http/request.hpp @@ -3,10 +3,10 @@ #include -namespace nall { +namespace nall { namespace HTTP { -struct httpRequest : httpMessage { - using type = httpRequest; +struct Request : Message { + using type = Request; enum class RequestType : unsigned { None, Head, Get, Post }; @@ -28,9 +28,9 @@ struct httpRequest : httpMessage { auto path() const -> string { return _path; } auto setPath(const string& value) -> void { _path = value; } - auto appendHeader(const string& name, const string& value = "") -> type& { return httpMessage::appendHeader(name, value), *this; } - auto removeHeader(const string& name) -> type& { return httpMessage::removeHeader(name), *this; } - auto setHeader(const string& name, const string& value = "") -> type& { return httpMessage::setHeader(name, value), *this; } + auto appendHeader(const string& name, const string& value = "") -> type& { return Message::appendHeader(name, value), *this; } + auto removeHeader(const string& name) -> type& { return Message::removeHeader(name), *this; } + auto setHeader(const string& name, const string& value = "") -> type& { return Message::setHeader(name, value), *this; } auto cookie(const string& name) const -> string { return _cookie.get(name); } auto setCookie(const string& name, const string& value = "") -> void { _cookie.set(name, value); } @@ -46,12 +46,12 @@ struct httpRequest : httpMessage { string _ip; RequestType _requestType = RequestType::None; string _path; - httpVariables _cookie; - httpVariables _get; - httpVariables _post; + Variables _cookie; + Variables _get; + Variables _post; }; -auto httpRequest::head(const function& callback) const -> bool { +auto Request::head(const function& callback) const -> bool { if(!callback) return false; string output; @@ -79,7 +79,7 @@ auto httpRequest::head(const function& callback return callback(output.binary(), output.size()); } -auto httpRequest::setHead() -> bool { +auto Request::setHead() -> bool { lstring headers = _head.split("\n"); string request = headers.takeFirst().rtrim("\r"); string requestHost; @@ -130,7 +130,7 @@ auto httpRequest::setHead() -> bool { return true; } -auto httpRequest::body(const function& callback) const -> bool { +auto Request::body(const function& callback) const -> bool { if(!callback) return false; if(_body) { @@ -140,7 +140,7 @@ auto httpRequest::body(const function& callback return true; } -auto httpRequest::setBody() -> bool { +auto Request::setBody() -> bool { if(requestType() == RequestType::Post) { if(header("Content-Type").iequals("application/x-www-form-urlencoded")) { for(auto& block : _body.split("&")) { @@ -153,6 +153,6 @@ auto httpRequest::setBody() -> bool { return true; } -} +}} #endif diff --git a/nall/http/response.hpp b/nall/http/response.hpp index 07d80bc7..c2353118 100644 --- a/nall/http/response.hpp +++ b/nall/http/response.hpp @@ -3,13 +3,13 @@ #include -namespace nall { +namespace nall { namespace HTTP { -struct httpResponse : httpMessage { - using type = httpResponse; +struct Response : Message { + using type = Response; - httpResponse() = default; - httpResponse(const httpRequest& request) { setRequest(request); } + Response() = default; + Response(const Request& request) { setRequest(request); } explicit operator bool() const { return responseType() != 0; } auto operator()(unsigned responseType) -> type& { return setResponseType(responseType); } @@ -20,15 +20,15 @@ struct httpResponse : httpMessage { inline auto body(const function& callback) const -> bool; inline auto setBody() -> bool; - auto request() const -> const httpRequest* { return _request; } - auto setRequest(const httpRequest& value) -> type& { _request = &value; return *this; } + auto request() const -> const Request* { return _request; } + auto setRequest(const Request& value) -> type& { _request = &value; return *this; } auto responseType() const -> unsigned { return _responseType; } auto setResponseType(unsigned value) -> type& { _responseType = value; return *this; } - auto appendHeader(const string& name, const string& value = "") -> type& { return httpMessage::appendHeader(name, value), *this; } - auto removeHeader(const string& name) -> type& { return httpMessage::removeHeader(name), *this; } - auto setHeader(const string& name, const string& value = "") -> type& { return httpMessage::setHeader(name, value), *this; } + auto appendHeader(const string& name, const string& value = "") -> type& { return Message::appendHeader(name, value), *this; } + auto removeHeader(const string& name) -> type& { return Message::removeHeader(name), *this; } + auto setHeader(const string& name, const string& value = "") -> type& { return Message::setHeader(name, value), *this; } auto hasData() const -> bool { return (bool)_data; } auto data() const -> const vector& { return _data; } @@ -49,14 +49,14 @@ struct httpResponse : httpMessage { inline auto findResponseType() const -> string; inline auto setFileETag() -> void; - const httpRequest* _request = nullptr; + const Request* _request = nullptr; unsigned _responseType = 0; vector _data; string _file; string _text; }; -auto httpResponse::head(const function& callback) const -> bool { +auto Response::head(const function& callback) const -> bool { if(!callback) return false; string output; @@ -91,7 +91,7 @@ auto httpResponse::head(const function& callbac return callback(output.binary(), output.size()); } -auto httpResponse::setHead() -> bool { +auto Response::setHead() -> bool { lstring headers = _head.split("\n"); string response = headers.takeFirst().rtrim("\r"); @@ -111,7 +111,7 @@ auto httpResponse::setHead() -> bool { return true; } -auto httpResponse::body(const function& callback) const -> bool { +auto Response::body(const function& callback) const -> bool { if(!callback) return false; if(!hasBody()) return true; bool chunked = header("Transfer-Encoding") == "chunked"; @@ -143,13 +143,13 @@ auto httpResponse::body(const function& callbac return true; } -auto httpResponse::setBody() -> bool { +auto Response::setBody() -> bool { return true; } -auto httpResponse::hasBody() const -> bool { +auto Response::hasBody() const -> bool { if(auto request = this->request()) { - if(request->requestType() == httpRequest::RequestType::Head) return false; + if(request->requestType() == Request::RequestType::Head) return false; } if(responseType() == 301) return false; if(responseType() == 302) return false; @@ -159,7 +159,7 @@ auto httpResponse::hasBody() const -> bool { return true; } -auto httpResponse::findContentLength() const -> unsigned { +auto Response::findContentLength() const -> unsigned { if(auto contentLength = header("Content-Length")) return decimal(contentLength); if(_body) return _body.size(); if(hasData()) return data().size(); @@ -168,14 +168,14 @@ auto httpResponse::findContentLength() const -> unsigned { return findResponseType().size(); } -auto httpResponse::findContentType() const -> string { +auto Response::findContentType() const -> string { if(auto contentType = header("Content-Type")) return contentType; if(hasData()) return "application/octet-stream"; if(hasFile()) return findContentType(file().suffixname()); return "text/html; charset=utf-8"; } -auto httpResponse::findContentType(const string& s) const -> string { +auto Response::findContentType(const string& s) const -> string { if(s == ".7z" ) return "application/x-7z-compressed"; if(s == ".avi" ) return "video/avi"; if(s == ".bml" ) return "text/plain; charset=utf-8"; @@ -209,7 +209,7 @@ auto httpResponse::findContentType(const string& s) const -> string { return "application/octet-stream"; //binary } -auto httpResponse::findResponseType() const -> string { +auto Response::findResponseType() const -> string { switch(responseType()) { case 200: return "200 OK"; case 301: return "301 Moved Permanently"; @@ -227,13 +227,13 @@ auto httpResponse::findResponseType() const -> string { return "501 Not Implemented"; } -auto httpResponse::setData(const vector& value) -> type& { +auto Response::setData(const vector& value) -> type& { _data = value; setHeader("Content-Length", value.size()); return *this; } -auto httpResponse::setFile(const string& value) -> type& { +auto Response::setFile(const string& value) -> type& { _file = value; string eTag = {"\"", string::datetime(file::timestamp(value, file::time::modify)), "\""}; setHeader("Content-Length", file::size(value)); @@ -242,12 +242,12 @@ auto httpResponse::setFile(const string& value) -> type& { return *this; } -auto httpResponse::setText(const string& value) -> type& { +auto Response::setText(const string& value) -> type& { _text = value; setHeader("Content-Length", value.size()); return *this; } -} +}} #endif diff --git a/nall/http/role.hpp b/nall/http/role.hpp index 248cc0bd..19210352 100644 --- a/nall/http/role.hpp +++ b/nall/http/role.hpp @@ -1,15 +1,15 @@ #ifndef NALL_HTTP_ROLE_HPP #define NALL_HTTP_ROLE_HPP -//httpRole: base class for httpClient and httpServer +//Role: base class for Client and Server //provides shared functionality #include #include -namespace nall { +namespace nall { namespace HTTP { -struct httpRole { +struct Role { struct Settings { signed connectionLimit = 1024; //server signed headSizeLimit = 16384; //client, server @@ -21,11 +21,11 @@ struct httpRole { } settings; inline auto configure(const string& parameters) -> bool; - inline auto download(signed fd, httpMessage& message) -> bool; - inline auto upload(signed fd, const httpMessage& message) -> bool; + inline auto download(signed fd, Message& message) -> bool; + inline auto upload(signed fd, const Message& message) -> bool; }; -auto httpRole::configure(const string& parameters) -> bool { +auto Role::configure(const string& parameters) -> bool { auto document = BML::unserialize(parameters); for(auto parameter : document) { auto name = parameter.name(); @@ -43,7 +43,7 @@ auto httpRole::configure(const string& parameters) -> bool { return true; } -auto httpRole::download(signed fd, httpMessage& message) -> bool { +auto Role::download(signed fd, Message& message) -> bool { auto& head = message._head; auto& body = message._body; string chunk; @@ -112,14 +112,14 @@ auto httpRole::download(signed fd, httpMessage& message) -> bool { if(!chunked) { body.resize(body.size() + length); - memory::copy(body.pointer() + body.size() - length, p, length); + memory::copy(body.get() + body.size() - length, p, length); p += length; length = 0; } else { signed transferLength = min(length, chunkLength); body.resize(body.size() + transferLength); - memory::copy(body.pointer() + body.size() - transferLength, p, transferLength); + memory::copy(body.get() + body.size() - transferLength, p, transferLength); p += transferLength; length -= transferLength; @@ -136,7 +136,7 @@ auto httpRole::download(signed fd, httpMessage& message) -> bool { return true; } -auto httpRole::upload(signed fd, const httpMessage& message) -> bool { +auto Role::upload(signed fd, const Message& message) -> bool { auto transfer = [&](const uint8_t* data, unsigned size) -> bool { while(size) { signed length = send(fd, data, min(size, settings.chunkSize), MSG_NOSIGNAL); @@ -156,6 +156,6 @@ auto httpRole::upload(signed fd, const httpMessage& message) -> bool { return false; } -} +}} #endif diff --git a/nall/http/server.hpp b/nall/http/server.hpp index bd073af8..d9e1f176 100644 --- a/nall/http/server.hpp +++ b/nall/http/server.hpp @@ -4,17 +4,17 @@ #include #include -namespace nall { +namespace nall { namespace HTTP { -struct httpServer : httpRole, service { +struct Server : Role, service { inline auto open(unsigned port = 8080, const string& serviceName = "", const string& command = "") -> bool; - inline auto main(const function& function = {}) -> void; + inline auto main(const function& function = {}) -> void; inline auto scan() -> string; inline auto close() -> void; - ~httpServer() { close(); } + ~Server() { close(); } private: - function callback; + function callback; std::atomic connections{0}; signed fd4 = -1; @@ -32,7 +32,7 @@ private: auto ipv6_scan() -> bool; }; -auto httpServer::open(unsigned port, const string& serviceName, const string& command) -> bool { +auto Server::open(unsigned port, const string& serviceName, const string& command) -> bool { if(serviceName) { if(!service::command(serviceName, command)) return false; } @@ -94,11 +94,11 @@ auto httpServer::open(unsigned port, const string& serviceName, const string& co return ipv4() || ipv6(); } -auto httpServer::main(const function& function) -> void { +auto Server::main(const function& function) -> void { callback = function; } -auto httpServer::scan() -> string { +auto Server::scan() -> string { if(auto command = service::receive()) return command; if(connections >= settings.connectionLimit) return "busy"; if(ipv4() && ipv4_scan()) return "ok"; @@ -106,7 +106,7 @@ auto httpServer::scan() -> string { return "idle"; } -auto httpServer::ipv4_scan() -> bool { +auto Server::ipv4_scan() -> bool { struct pollfd query = {0}; query.fd = fd4; query.events = POLLIN; @@ -127,7 +127,7 @@ auto httpServer::ipv4_scan() -> bool { uint32_t ip = ntohl(settings.sin_addr.s_addr); - httpRequest request; + Request request; request._ipv6 = false; request._ip = { (uint8_t)(ip >> 24), ".", @@ -140,7 +140,7 @@ auto httpServer::ipv4_scan() -> bool { auto response = callback(request); upload(clientfd, response); } else { - upload(clientfd, httpResponse()); //"501 Not Implemented" + upload(clientfd, Response()); //"501 Not Implemented" } ::close(clientfd); @@ -153,7 +153,7 @@ auto httpServer::ipv4_scan() -> bool { return false; } -auto httpServer::ipv6_scan() -> bool { +auto Server::ipv6_scan() -> bool { struct pollfd query = {0}; query.fd = fd6; query.events = POLLIN; @@ -172,23 +172,41 @@ auto httpServer::ipv6_scan() -> bool { clientfd = accept(fd6, (struct sockaddr*)&settings, &socklen); if(clientfd < 0) return; - unsigned char* ip = settings.sin6_addr.s6_addr; - uint16_t ipSegment[8] = {0}; + uint8_t* ip = settings.sin6_addr.s6_addr; + uint16_t ipSegment[8]; for(auto n : range(8)) ipSegment[n] = ip[n * 2 + 0] * 256 + ip[n * 2 + 1]; - httpRequest request; + Request request; request._ipv6 = true; + //RFC5952 IPv6 encoding: the first longest 2+ consecutive zero-sequence is compressed to "::" + signed zeroOffset = -1; + signed zeroLength = 0; + signed zeroCounter = 0; for(auto n : range(8)) { - uint16_t value = ip[n * 2 + 0] * 256 + ip[n * 2 + 1]; - request._ip.append(hex(value, 4L)); - if(n != 7) request._ip.append(":"); + uint16_t value = ipSegment[n]; + if(value == 0) zeroCounter++; + if(zeroCounter > zeroLength) { + zeroLength = zeroCounter; + zeroOffset = 1 + n - zeroLength; + } + if(value != 0) zeroCounter = 0; + } + if(zeroLength == 1) zeroOffset = -1; + for(unsigned n = 0; n < 8;) { + if(n == zeroOffset) { + request._ip.append(n == 0 ? "::" : ":"); + n += zeroLength; + } else { + uint16_t value = ipSegment[n]; + request._ip.append(hex(value), n++ != 7 ? ":" : ""); + } } if(download(clientfd, request) && callback) { auto response = callback(request); upload(clientfd, response); } else { - upload(clientfd, httpResponse()); //"501 Not Implemented" + upload(clientfd, Response()); //"501 Not Implemented" } ::close(clientfd); @@ -201,11 +219,11 @@ auto httpServer::ipv6_scan() -> bool { return false; } -auto httpServer::close() -> void { +auto Server::close() -> void { ipv4_close(); ipv6_close(); } -} +}} #endif diff --git a/nall/image.hpp b/nall/image.hpp index b1c865ea..c39f356f 100644 --- a/nall/image.hpp +++ b/nall/image.hpp @@ -3,10 +3,10 @@ #include -#include #include #include #include +#include #include #include #include diff --git a/nall/image/base.hpp b/nall/image/base.hpp index e20ee1b1..e7c4c059 100644 --- a/nall/image/base.hpp +++ b/nall/image/base.hpp @@ -118,6 +118,7 @@ private: //load.hpp inline auto loadBMP(const string& filename) -> bool; + inline auto loadBMP(const uint8_t* data, unsigned size) -> bool; inline auto loadPNG(const string& filename) -> bool; inline auto loadPNG(const uint8_t* data, unsigned size) -> bool; diff --git a/nall/image/core.hpp b/nall/image/core.hpp index 9939da5a..92a28743 100644 --- a/nall/image/core.hpp +++ b/nall/image/core.hpp @@ -26,11 +26,17 @@ image::image(const string& filename) { } image::image(const vector& buffer) { - loadPNG(buffer.data(), buffer.size()); + auto data = buffer.data(); + auto size = buffer.size(); + if(0); + else if(data[0] == 'B' && data[1] == 'M') loadBMP(data, size); + else if(data[1] == 'P' && data[2] == 'N' && data[3] == 'G') loadPNG(data, size); } image::image(const uint8_t* data, unsigned size) { - loadPNG(data, size); + if(0); + else if(data[0] == 'B' && data[1] == 'M') loadBMP(data, size); + else if(data[1] == 'P' && data[2] == 'N' && data[3] == 'G') loadPNG(data, size); } image::image() { diff --git a/nall/image/load.hpp b/nall/image/load.hpp index 99cab499..f783c5ba 100644 --- a/nall/image/load.hpp +++ b/nall/image/load.hpp @@ -4,16 +4,21 @@ namespace nall { auto image::loadBMP(const string& filename) -> bool { - uint32_t* outputData; - unsigned outputWidth, outputHeight; - if(bmp::read(filename, outputData, outputWidth, outputHeight) == false) return false; + if(!file::exists(filename)) return false; + auto buffer = file::read(filename); + return loadBMP(buffer.data(), buffer.size()); +} - allocate(outputWidth, outputHeight); - const uint32_t* sp = outputData; +auto image::loadBMP(const uint8_t* bmpData, unsigned bmpSize) -> bool { + Decode::BMP source; + if(!source.load(bmpData, bmpSize)) return false; + + allocate(source.width(), source.height()); + const uint32_t* sp = source.data(); uint8_t* dp = _data; - for(unsigned y = 0; y < outputHeight; y++) { - for(unsigned x = 0; x < outputWidth; x++) { + for(unsigned y = 0; y < _height; y++) { + for(unsigned x = 0; x < _width; x++) { uint32_t color = *sp++; uint64_t a = normalize((uint8_t)(color >> 24), 8, _alpha.depth()); uint64_t r = normalize((uint8_t)(color >> 16), 8, _red.depth()); @@ -23,9 +28,6 @@ auto image::loadBMP(const string& filename) -> bool { dp += stride(); } } - - delete[] outputData; - return true; } auto image::loadPNG(const string& filename) -> bool { @@ -36,7 +38,7 @@ auto image::loadPNG(const string& filename) -> bool { auto image::loadPNG(const uint8_t* pngData, unsigned pngSize) -> bool { Decode::PNG source; - if(source.decode(pngData, pngSize) == false) return false; + if(!source.load(pngData, pngSize)) return false; allocate(source.info.width, source.info.height); const uint8_t* sp = source.data; diff --git a/nall/maybe.hpp b/nall/maybe.hpp index 425f98e0..f1ac3675 100644 --- a/nall/maybe.hpp +++ b/nall/maybe.hpp @@ -6,110 +6,87 @@ namespace nall { struct nothing_t {}; static nothing_t nothing; -template -class maybe { - T* value = nullptr; +template +struct maybe { + inline maybe() {} + inline maybe(nothing_t) {} + inline maybe(const T& source) { operator=(source); } + inline maybe(T&& source) { operator=(move(source)); } + inline maybe(const maybe& source) { operator=(source); } + inline maybe(maybe&& source) { operator=(move(source)); } + inline ~maybe() { reset(); } -public: - maybe() {} - maybe(nothing_t) {} - maybe(const T& source) { operator=(source); } - maybe(const maybe& source) { operator=(source); } - maybe(maybe&& source) { operator=(move(source)); } - ~maybe() { reset(); } + inline auto operator=(nothing_t) -> maybe& { reset(); return *this; } + inline auto operator=(const T& source) -> maybe& { reset(); _valid = true; new(&_value.t) T(source); return *this; } + inline auto operator=(T&& source) -> maybe& { reset(); _valid = true; new(&_value.t) T(move(source)); return *this; } - auto operator=(nothing_t) -> maybe& { reset(); return *this; } - auto operator=(const T& source) -> maybe& { reset(); value = new T(source); return *this; } - auto operator=(const maybe& source) -> maybe& { reset(); if(source) value = new T(source()); return *this; } - auto operator=(maybe&& source) -> maybe& { reset(); value = source.value; source.value = nullptr; return *this; } - - auto operator==(const maybe& source) const -> bool { - if(value && source.value) return *value == *source.value; - return !value && !source.value; + inline auto operator=(const maybe& source) -> maybe& { + if(this == &source) return *this; + reset(); + if(_valid = source._valid) new(&_value.t) T(source.get()); + return *this; } - auto operator!=(const maybe& source) const -> bool { return !operator==(source); } - explicit operator bool() const { return value; } - auto operator->() -> T* { assert(value); return value; } - auto operator->() const -> T* { assert(value); return value; } - auto operator*() -> T& { assert(value); return *value; } - auto operator*() const -> T& { assert(value); return *value; } - auto operator()() -> T& { assert(value); return *value; } - auto operator()() const -> T& { assert(value); return *value; } - auto operator()(const T& invalid) const -> T& { if(value) return *value; return invalid; } + inline auto operator=(maybe&& source) -> maybe& { + if(this == &source) return *this; + reset(); + if(_valid = source._valid) new(&_value.t) T(move(source.get())); + source._valid = false; + return *this; + } - auto empty() const -> bool { return value == nullptr; } - auto reset() -> void { if(value) { delete value; value = nullptr; } } - auto swap(maybe& source) -> void { std::swap(value, source.value); } + inline explicit operator bool() const { return _valid; } + inline auto reset() -> void { if(_valid) { _value.t.~T(); _valid = false; } } + inline auto data() -> T* { return _valid ? &_value.t : nullptr; } + inline auto get() -> T& { assert(_valid); return _value.t; } + + inline auto data() const -> const T* { return ((maybe*)this)->data(); } + inline auto get() const -> const T& { return ((maybe*)this)->get(); } + inline auto operator->() -> T* { return data(); } + inline auto operator->() const -> const T* { return data(); } + inline auto operator*() -> T& { return get(); } + inline auto operator*() const -> const T& { return get(); } + inline auto operator()() -> T& { return get(); } + inline auto operator()() const -> const T& { return get(); } + inline auto operator()(const T& invalid) const -> const T& { return _valid ? get() : invalid; } + +private: + union U { + T t; + U() {} + ~U() {} + } _value; + bool _valid = false; }; template -class maybe { - T* value = nullptr; +struct maybe { + inline maybe() : _value(nullptr) {} + inline maybe(nothing_t) : _value(nullptr) {} + inline maybe(const T& source) : _value((T*)&source) {} + inline maybe(const maybe& source) : _value(source._value) {} -public: - maybe() {} - maybe(nothing_t) {} - maybe(const T& source) { operator=(source); } - maybe(const maybe& source) { operator=(source); } - maybe(maybe&& source) { operator=(move(source)); } + inline auto operator=(nothing_t) -> maybe& { _value = nullptr; return *this; } + inline auto operator=(const T& source) -> maybe& { _value = (T*)&source; return *this; } + inline auto operator=(const maybe& source) -> maybe& { _value = source._value; return *this; } - auto operator=(nothing_t) -> maybe& { value = nullptr; return *this; } - auto operator=(const T& source) -> maybe& { value = (T*)&source; return *this; } - auto operator=(const maybe& source) -> maybe& { value = source.value; return *this; } - auto operator=(maybe&& source) -> maybe& { value = source.value; source.value = nullptr; return *this; } + inline explicit operator bool() const { return _value; } + inline auto reset() -> void { _value = nullptr; } + inline auto data() -> T* { return _value; } + inline auto get() -> T& { assert(_value); return *_value; } - auto operator==(const maybe& source) const -> bool { - if(value && source.value) return *value == *source.value; - return !value && !source.value; - } - auto operator!=(const maybe& source) const -> bool { return !operator==(source); } + inline auto data() const -> const T* { return ((maybe*)this)->data(); } + inline auto get() const -> const T& { return ((maybe*)this)->get(); } + inline auto operator->() -> T* { return data(); } + inline auto operator->() const -> const T* { return data(); } + inline auto operator*() -> T& { return get(); } + inline auto operator*() const -> const T& { return get(); } + inline auto operator()() -> T& { return get(); } + inline auto operator()() const -> const T& { return get(); } + inline auto operator()(const T& invalid) const -> const T& { return _value ? get() : invalid; } - explicit operator bool() const { return value; } - auto operator->() -> T* { assert(value); return value; } - auto operator->() const -> T* { assert(value); return *value; } - auto operator*() -> T& { assert(value); return *value; } - auto operator*() const -> T& { assert(value); return *value; } - auto operator()() -> T& { assert(value); return *value; } - auto operator()() const -> T& { assert(value); return *value; } - auto operator()(const T& invalid) const -> T& { if(value) return *value; return invalid; } - - auto empty() const -> bool { return value == nullptr; } - auto reset() -> void { value = nullptr; } - auto swap(maybe& source) -> void { std::swap(value, source.value); } -}; - -template -class maybe>> { - T value = 0; - bool valid = false; - -public: - maybe() {} - maybe(nothing_t) {} - maybe(const T& source) { operator=(source); } - maybe(const maybe& source) { operator=(source); } - maybe(maybe&& source) { operator=(move(source)); } - - auto operator=(nothing_t) -> maybe& { valid = false; return *this; } - auto operator=(const T& source) -> maybe& { valid = true; value = source; return *this; } - auto operator=(const maybe& source) -> maybe& { valid = source.valid; value = source.value; return *this; } - auto operator=(maybe&& source) -> maybe& { valid = source.valid; value = source.value; source.valid = false; return *this; } - - auto operator==(const maybe& source) const -> bool { - if(valid && source.valid) return value == source.value; - return !valid && !source.valid; - } - auto operator!=(const maybe& source) const -> bool { return !operator==(source); } - - explicit operator bool() const { return valid; } - auto operator*() const -> T { assert(valid); return value; } - auto operator()() const -> T { assert(valid); return value; } - auto operator()(const T& invalid) const -> T { if(valid) return value; return invalid; } - - auto empty() const -> bool { return !valid; } - auto reset() -> void { valid = false; } - auto swap(maybe& source) -> void { std::swap(valid, source.valid); std::swap(value, source.value); } +private: + T* _value; }; } diff --git a/nall/method.hpp b/nall/method.hpp deleted file mode 100644 index 36a203fe..00000000 --- a/nall/method.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef NALL_METHOD_HPP -#define NALL_METHOD_HPP - -//provides extension-method and chaining-method support to classes -//extension: class(function, params...); -//chaining: class[function](params...)[function](params...); - -//usage: -//struct object : method { -// using method::operator[]; //if object::operator[] defined -// using method::operator(); //if object::operator() defined -//}; - -//note: extension-methods would be obsolete if C++17 introduces unified function call syntax -//currently proposed as N4165 and N4174 - -namespace nall { - -template struct method { - template struct chain { - chain(T& self, const F& f) : self(self), f(f) {} - template auto operator()(P&&... p) -> T& { - return f(self, forward

(p)...), self; - } - private: - T& self; - const F& f; - }; - - template struct const_chain { - const_chain(const T& self, const F& f) : self(self), f(f) {} - template auto operator()(P&&... p) const -> const T& { - return f(self, forward

(p)...), self; - } - private: - const T& self; - const F& f; - }; - - template>> - auto operator[](const F& f) -> chain { return chain((T&)*this, f); } - - template>> - auto operator[](const F& f) const -> const_chain { return const_chain((const T&)*this, f); } - - template>> - auto operator()(const F& f, P&&... p) -> decltype(f((T&)*this, forward

(p)...)) { - return f((T&)*this, forward

(p)...); - } - - template>> - auto operator()(const F& f, P&&... p) const -> decltype(f((const T&)*this, forward

(p)...)) { - return f((const T&)*this, forward

(p)...); - } -}; - -} - -#endif diff --git a/nall/nall.hpp b/nall/nall.hpp index 86566576..a2647cd0 100644 --- a/nall/nall.hpp +++ b/nall/nall.hpp @@ -17,15 +17,14 @@ #include #include #include -#include #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -46,7 +45,6 @@ #include #include #include -#include #include #include #include @@ -54,12 +52,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include diff --git a/nall/posix/service.hpp b/nall/posix/service.hpp index 206b2381..36cbe110 100644 --- a/nall/posix/service.hpp +++ b/nall/posix/service.hpp @@ -83,7 +83,7 @@ auto service::receive() -> string { if(auto data = shared.acquire()) { if(*data) { command.resize(4095); - memory::copy(command.pointer(), data, 4095); + memory::copy(command.get(), data, 4095); memory::fill(data, 4096); } shared.release(); diff --git a/nall/public-cast.hpp b/nall/public-cast.hpp deleted file mode 100644 index c9c4940d..00000000 --- a/nall/public-cast.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef NALL_PUBLIC_CAST_HPP -#define NALL_PUBLIC_CAST_HPP - -//this is a proof-of-concept-*only* C++ access-privilege elevation exploit. -//this code is 100% legal C++, per C++98 section 14.7.2 paragraph 8: -//"access checking rules do not apply to names in explicit instantiations." -//usage example: - -//struct N { typedef void (Class::*)(); }; -//template class public_cast; -//(class.*public_cast::value); - -//Class::Reference may be public, protected or private -//Class::Reference may be a function, object or variable - -namespace nall { - -template struct public_cast; - -template struct public_cast { - static typename T::type value; -}; - -template typename T::type public_cast::value; - -template struct public_cast { - static typename T::type value; -}; - -template typename T::type public_cast::value = public_cast::value = P; - -} - -#endif diff --git a/nall/set.hpp b/nall/set.hpp index 14121c5d..828e5e0b 100644 --- a/nall/set.hpp +++ b/nall/set.hpp @@ -29,14 +29,27 @@ template struct set { node_t* root = nullptr; unsigned nodes = 0; - auto operator=(const set& source) -> set& { copy(source); return *this; } - auto operator=(set&& source) -> set& { move(std::move(source)); return *this; } + set() = default; set(const set& source) { operator=(source); } set(set&& source) { operator=(move(source)); } set(std::initializer_list list) { for(auto& value : list) insert(value); } - set() = default; ~set() { reset(); } + auto operator=(const set& source) -> set& { + reset(); + copy(root, source.root); + nodes = source.nodes; + return *this; + } + + auto operator=(set&& source) -> set& { + root = source.root; + nodes = source.nodes; + source.root = nullptr; + source.nodes = 0; + return *this; + } + auto size() const -> unsigned { return nodes; } auto empty() const -> bool { return nodes == 0; } @@ -63,9 +76,9 @@ template struct set { return v->value; } - template auto insert(const T& value, Args&&... args) -> bool { + template auto insert(const T& value, P&&... p) -> bool { bool result = insert(value); - insert(forward(args)...) | result; + insert(forward

(p)...) | result; return result; } @@ -77,9 +90,9 @@ template struct set { return size() < count; } - template auto remove(const T& value, Args&&... args) -> bool { + template auto remove(const T& value, P&&... p) -> bool { bool result = remove(value); - return remove(forward(args)...) | result; + return remove(forward

(p)...) | result; } struct base_iterator { @@ -139,12 +152,6 @@ private: node = nullptr; } - auto copy(const set& source) -> void { - reset(); - copy(root, source.root); - nodes = source.nodes; - } - auto copy(node_t*& target, const node_t* source) -> void { if(!source) return; target = new node_t(source->value); @@ -153,13 +160,6 @@ private: copy(target->link[1], source->link[1]); } - auto move(set&& source) -> void { - root = source.root; - nodes = source.nodes; - source.root = nullptr; - source.nodes = 0; - } - auto find(node_t* node, const T& value) const -> node_t* { if(node == nullptr) return nullptr; if(node->value == value) return node; diff --git a/nall/storage.hpp b/nall/storage.hpp deleted file mode 100644 index 3d9b7bb7..00000000 --- a/nall/storage.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef NALL_STORAGE_HPP -#define NALL_STORAGE_HPP - -//generic abstraction layer for common storage operations against both files and directories -//these functions are not recursive; use directory::create() and directory::remove() for recursion - -#include -#include - -namespace nall { - -struct storage { - enum class time : unsigned { access, modify }; - - static auto exists(const string& name) -> bool; - static auto readable(const string& name) -> bool; - static auto writable(const string& name) -> bool; - static auto executable(const string& name) -> bool; - static auto uid(const string& name) -> unsigned; - static auto gid(const string& name) -> unsigned; - static auto mode(const string& name) -> unsigned; - static auto timestamp(const string& name, storage::time mode = storage::time::modify) -> time_t; - - static auto create(const string& name, unsigned permissions = 0755) -> bool; - static auto rename(const string& name, const string& targetname) -> bool; - static auto remove(const string& name) -> bool; -}; - -inline auto storage::exists(const string& name) -> bool { - return access(name, F_OK) == 0; -} - -inline auto storage::readable(const string& name) -> bool { - return access(name, R_OK) == 0; -} - -inline auto storage::writable(const string& name) -> bool { - return access(name, W_OK) == 0; -} - -inline auto storage::executable(const string& name) -> bool { - return access(name, X_OK) == 0; -} - -inline auto storage::uid(const string& name) -> unsigned { - struct stat data = {0}; - stat(name, &data); - return data.st_uid; -} - -inline auto storage::gid(const string& name) -> unsigned { - struct stat data = {0}; - stat(name, &data); - return data.st_gid; -} - -inline auto storage::mode(const string& name) -> unsigned { - struct stat data = {0}; - stat(name, &data); - return data.st_mode; -} - -inline auto storage::timestamp(const string& name, storage::time mode) -> time_t { - struct stat data = {0}; - stat(name, &data); - switch(mode) { - case storage::time::access: return data.st_atime; - case storage::time::modify: return data.st_mtime; - } - throw; -} - -//returns true if 'name' already exists -inline auto storage::create(const string& name, unsigned permissions) -> bool { - if(storage::exists(name)) return true; - if(name.endsWith("/")) return mkdir(name, permissions) == 0; - int fd = open(name, O_CREAT | O_EXCL, permissions); - if(fd < 0) return false; - return close(fd), true; -} - -//returns false if 'name' and 'targetname' are on different file systems (requires copy) -inline auto storage::rename(const string& name, const string& targetname) -> bool { - return ::rename(name, targetname) == 0; -} - -//returns false if 'name' is a directory that is not empty -inline auto storage::remove(const string& name) -> bool { - if(name.endsWith("/")) return rmdir(name) == 0; - return unlink(name) == 0; -} - -} - -#endif diff --git a/nall/string.hpp b/nall/string.hpp index 0a8f53ad..88e1b909 100644 --- a/nall/string.hpp +++ b/nall/string.hpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/nall/string/allocator/adaptive.hpp b/nall/string/allocator/adaptive.hpp index 0a9f75fe..137b8ecf 100644 --- a/nall/string/allocator/adaptive.hpp +++ b/nall/string/allocator/adaptive.hpp @@ -22,7 +22,7 @@ namespace nall { string::string() : _data(nullptr), _capacity(SSO - 1), _size(0) { } -auto string::pointer() -> char* { +auto string::get() -> char* { if(_capacity < SSO) return _text; if(*_refs > 1) _copy(); return _data; @@ -59,7 +59,7 @@ auto string::reserve(unsigned capacity) -> type& { auto string::resize(unsigned size) -> type& { reserve(size); - pointer()[_size = size] = 0; + get()[_size = size] = 0; return *this; } diff --git a/nall/string/allocator/copy-on-write.hpp b/nall/string/allocator/copy-on-write.hpp index 574dde97..2816963e 100644 --- a/nall/string/allocator/copy-on-write.hpp +++ b/nall/string/allocator/copy-on-write.hpp @@ -5,7 +5,7 @@ namespace nall { string::string() : _data(nullptr), _refs(nullptr), _capacity(0), _size(0) { } -auto string::pointer() -> char* { +auto string::get() -> char* { static char _null[] = ""; if(!_data) return _null; if(*_refs > 1) _data = _copy(); //make unique for write operations @@ -38,7 +38,7 @@ auto string::reserve(unsigned capacity) -> type& { auto string::resize(unsigned size) -> type& { reserve(size); - pointer()[_size = size] = 0; + get()[_size = size] = 0; return *this; } diff --git a/nall/string/allocator/small-string-optimization.hpp b/nall/string/allocator/small-string-optimization.hpp index 0430abbf..e71de3a1 100644 --- a/nall/string/allocator/small-string-optimization.hpp +++ b/nall/string/allocator/small-string-optimization.hpp @@ -26,7 +26,7 @@ string::string() { _size = 0; } -auto string::pointer() -> char* { +auto string::get() -> char* { if(_capacity < SSO) return _text; return _data; } @@ -60,7 +60,7 @@ auto string::reserve(unsigned capacity) -> type& { auto string::resize(unsigned size) -> type& { reserve(size); - pointer()[_size = size] = 0; + get()[_size = size] = 0; return *this; } diff --git a/nall/string/allocator/vector.hpp b/nall/string/allocator/vector.hpp index 856221a5..31b25b08 100644 --- a/nall/string/allocator/vector.hpp +++ b/nall/string/allocator/vector.hpp @@ -19,7 +19,7 @@ cons: namespace nall { -auto string::pointer() -> char* { +auto string::get() -> char* { if(_capacity == 0) reserve(1); return _data; } @@ -47,7 +47,7 @@ auto string::reserve(unsigned capacity) -> type& { auto string::resize(unsigned size) -> type& { reserve(size); - pointer()[_size = size] = 0; + get()[_size = size] = 0; return *this; } diff --git a/nall/string/base.hpp b/nall/string/base.hpp index 23eecfd7..1f4ec0cf 100644 --- a/nall/string/base.hpp +++ b/nall/string/base.hpp @@ -182,7 +182,7 @@ protected: public: inline string(); - inline auto pointer() -> char*; + inline auto get() -> char*; inline auto data() const -> const char*; inline auto reset() -> type&; inline auto reserve(unsigned) -> type&; @@ -214,8 +214,8 @@ public: string(const string& source) : string() { operator=(source); } string(string&& source) : string() { operator=(std::move(source)); } - auto begin() -> char* { return &pointer()[0]; } - auto end() -> char* { return &pointer()[size()]; } + auto begin() -> char* { return &get()[0]; } + auto end() -> char* { return &get()[size()]; } auto begin() const -> const char* { return &data()[0]; } auto end() const -> const char* { return &data()[size()]; } diff --git a/nall/string/convert.hpp b/nall/string/convert.hpp index 3ffb5a6d..86b38241 100644 --- a/nall/string/convert.hpp +++ b/nall/string/convert.hpp @@ -3,7 +3,7 @@ namespace nall { auto downcase(string& self) -> string& { - char* p = self.pointer(); + char* p = self.get(); for(unsigned n = 0; n < self.size(); n++) { if(p[n] >= 'A' && p[n] <= 'Z') p[n] += 0x20; } @@ -11,7 +11,7 @@ auto downcase(string& self) -> string& { } auto qdowncase(string& self) -> string& { - char* p = self.pointer(); + char* p = self.get(); for(unsigned n = 0, quoted = 0; n < self.size(); n++) { if(p[n] == '\"') quoted ^= 1; if(!quoted && p[n] >= 'A' && p[n] <= 'Z') p[n] += 0x20; @@ -20,7 +20,7 @@ auto qdowncase(string& self) -> string& { } auto upcase(string& self) -> string& { - char* p = self.pointer(); + char* p = self.get(); for(unsigned n = 0; n < self.size(); n++) { if(p[n] >= 'a' && p[n] <= 'z') p[n] -= 0x20; } @@ -28,7 +28,7 @@ auto upcase(string& self) -> string& { } auto qupcase(string& self) -> string& { - char* p = self.pointer(); + char* p = self.get(); for(unsigned n = 0, quoted = 0; n < self.size(); n++) { if(p[n] == '\"') quoted ^= 1; if(!quoted && p[n] >= 'a' && p[n] <= 'z') p[n] -= 0x20; @@ -38,7 +38,7 @@ auto qupcase(string& self) -> string& { auto transform(string& self, rstring from, rstring to) -> string& { if(from.size() != to.size() || from.size() == 0) return self; //patterns must be the same length - char* p = self.pointer(); + char* p = self.get(); for(unsigned n = 0; n < self.size(); n++) { for(unsigned s = 0; s < from.size(); s++) { if(p[n] == from[s]) { diff --git a/nall/string/core.hpp b/nall/string/core.hpp index dee9bfd0..0c19e700 100644 --- a/nall/string/core.hpp +++ b/nall/string/core.hpp @@ -43,7 +43,7 @@ template auto _append(string& self, const stringify& source) -> s unsigned size = self.size(); unsigned length = source.size(); self.resize(size + length); - memory::copy(self.pointer() + size, source.data(), length); + memory::copy(self.get() + size, source.data(), length); return self; } diff --git a/nall/string/format.hpp b/nall/string/format.hpp index 739895d2..593bd682 100644 --- a/nall/string/format.hpp +++ b/nall/string/format.hpp @@ -54,7 +54,7 @@ auto string::format(const nall::format& params) -> type& { } resize(size); - memory::copy(pointer(), data, size); + memory::copy(get(), data, size); memory::free(data); return *this; } @@ -76,7 +76,7 @@ template auto print(P&&... p) -> void { auto integer(intmax_t value, long precision, char padchar) -> string { string buffer; buffer.resize(1 + sizeof(intmax_t) * 3); - char* p = buffer.pointer(); + char* p = buffer.get(); bool negative = value < 0; value = abs(value); @@ -95,7 +95,7 @@ auto integer(intmax_t value, long precision, char padchar) -> string { auto decimal(uintmax_t value, long precision, char padchar) -> string { string buffer; buffer.resize(sizeof(uintmax_t) * 3); - char* p = buffer.pointer(); + char* p = buffer.get(); unsigned size = 0; do { @@ -111,7 +111,7 @@ auto decimal(uintmax_t value, long precision, char padchar) -> string { auto hex(uintmax_t value, long precision, char padchar) -> string { string buffer; buffer.resize(sizeof(uintmax_t) * 2); - char* p = buffer.pointer(); + char* p = buffer.get(); unsigned size = 0; do { @@ -128,7 +128,7 @@ auto hex(uintmax_t value, long precision, char padchar) -> string { auto octal(uintmax_t value, long precision, char padchar) -> string { string buffer; buffer.resize(sizeof(uintmax_t) * 3); - char* p = buffer.pointer(); + char* p = buffer.get(); unsigned size = 0; do { @@ -144,7 +144,7 @@ auto octal(uintmax_t value, long precision, char padchar) -> string { auto binary(uintmax_t value, long precision, char padchar) -> string { string buffer; buffer.resize(sizeof(uintmax_t) * 8); - char* p = buffer.pointer(); + char* p = buffer.get(); unsigned size = 0; do { @@ -170,7 +170,7 @@ auto pointer(uintptr_t value, long precision) -> string { auto real(long double value) -> string { string temp; temp.resize(real(nullptr, value)); - real(temp.pointer(), value); + real(temp.get(), value); return temp; } diff --git a/nall/string/markup/bml.hpp b/nall/string/markup/bml.hpp index 17d62b08..d9d87a27 100644 --- a/nall/string/markup/bml.hpp +++ b/nall/string/markup/bml.hpp @@ -109,7 +109,7 @@ protected: auto parse(string document) -> void { //in order to simplify the parsing logic; we do an initial pass to normalize the data //the below code will turn '\r\n' into '\n'; skip empty lines; and skip comment lines - char* p = document.pointer(), *output = p; + char* p = document.get(), *output = p; while(*p) { char* origin = p; bool empty = true; diff --git a/nall/string/markup/xml.hpp b/nall/string/markup/xml.hpp index 16a6d2c9..c1bbcac8 100644 --- a/nall/string/markup/xml.hpp +++ b/nall/string/markup/xml.hpp @@ -52,7 +52,7 @@ protected: return; #endif - char* output = target.pointer(); + char* output = target.get(); while(length) { if(*source == '&') { if(!memory::compare(source, "<", 4)) { *output++ = '<'; source += 4; length -= 4; continue; } diff --git a/nall/string/path.hpp b/nall/string/path.hpp index 5ef4b7be..19ffd41d 100644 --- a/nall/string/path.hpp +++ b/nall/string/path.hpp @@ -48,10 +48,11 @@ auto basename(const string& self) -> string { // /parent/child.type/(name).type auto prefixname(const string& self) -> string { const char* p = self.data() + self.size() - 1, *last = p; - for(signed offset = self.size() - 1, suffix = 0; offset >= 0; offset--, p--) { + for(signed offset = self.size() - 1, suffix = -1; offset >= 0; offset--, p--) { if(*p == '/' && p == last) continue; - if(*p == '/') return slice(self, offset + 1, suffix ? suffix - offset - 1 : 0).rtrim("/"); - if(*p == '.' && suffix == 0) suffix = offset; + if(*p == '/') return slice(self, offset + 1, suffix >= 0 ? suffix - offset - 1 : 0).rtrim("/"); + if(*p == '.' && suffix == -1) { suffix = offset; continue; } + if(offset == 0) return slice(self, offset, suffix).rtrim("/"); } return ""; } diff --git a/nall/string/replace.hpp b/nall/string/replace.hpp index 96cd2537..a6e61099 100644 --- a/nall/string/replace.hpp +++ b/nall/string/replace.hpp @@ -25,7 +25,7 @@ auto _replace(string& self, rstring from, rstring to, long limit) -> string& { //in-place overwrite if(to.size() == from.size()) { - char* p = self.pointer(); + char* p = self.get(); for(signed n = 0, remaining = matches, quoted = 0; n <= size - (signed)from.size();) { if(Quoted) { if(p[n] == '\"') { quoted ^= 1; n++; continue; } if(quoted) { n++; continue; } } @@ -40,7 +40,7 @@ auto _replace(string& self, rstring from, rstring to, long limit) -> string& { //left-to-right shrink else if(to.size() < from.size()) { - char* p = self.pointer(); + char* p = self.get(); signed offset = 0; signed base = 0; @@ -64,7 +64,7 @@ auto _replace(string& self, rstring from, rstring to, long limit) -> string& { //right-to-left expand else if(to.size() > from.size()) { self.resize(size + matches * (to.size() - from.size())); - char* p = self.pointer(); + char* p = self.get(); signed offset = self.size(); signed base = size; diff --git a/nall/string/split.hpp b/nall/string/split.hpp index ee4bc845..33f4c19a 100644 --- a/nall/string/split.hpp +++ b/nall/string/split.hpp @@ -18,7 +18,7 @@ template auto _split(lstring& self, rstring sourc string& s = self(matches); s.resize(n - base); - memory::copy(s.pointer(), p + base, n - base); + memory::copy(s.get(), p + base, n - base); n += find.size(); base = n; @@ -27,7 +27,7 @@ template auto _split(lstring& self, rstring sourc string& s = self(matches); s.resize(size - base); - memory::copy(s.pointer(), p + base, size - base); + memory::copy(s.get(), p + base, size - base); return self; } diff --git a/nall/string/utility.hpp b/nall/string/utility.hpp index bb8cb1d3..933bd2b4 100644 --- a/nall/string/utility.hpp +++ b/nall/string/utility.hpp @@ -18,7 +18,7 @@ auto string::read(const string& filename) -> string { rewind(fp); result.resize(filesize); - fread(result.pointer(), 1, filesize, fp); + auto unused = fread(result.get(), 1, filesize, fp); return fclose(fp), result; } @@ -29,7 +29,7 @@ auto string::repeat(const string& pattern, unsigned times) -> string { } auto fill(string& self, char fill) -> string& { - memory::fill(self.pointer(), self.size(), fill); + memory::fill(self.get(), self.size(), fill); return self; } @@ -42,14 +42,14 @@ auto hash(const string& self) -> unsigned { } auto remove(string& self, unsigned offset, unsigned length) -> string& { - char* p = self.pointer(); + char* p = self.get(); length = min(length, self.size()); memory::move(p + offset, p + offset + length, self.size() - length); return self.resize(self.size() - length); } auto reverse(string& self) -> string& { - char* p = self.pointer(); + char* p = self.get(); unsigned size = self.size(); unsigned pivot = size >> 1; for(signed x = 0, y = size - 1; x < pivot && y >= 0; x++, y--) std::swap(p[x], p[y]); @@ -67,13 +67,13 @@ auto size(string& self, signed length, char fill) -> string& { if(size < length) { //expand self.resize(length); - char* p = self.pointer(); + char* p = self.get(); unsigned displacement = length - size; if(right) memory::move(p + displacement, p, size); else p += size; while(displacement--) *p++ = fill; } else { //shrink - char* p = self.pointer(); + char* p = self.get(); unsigned displacement = size - length; if(right) memory::move(p, p + displacement, length); self.resize(length); @@ -87,7 +87,7 @@ auto slice(const string& self, signed offset, signed length) -> string { if(offset < self.size()) { if(length < 0) length = self.size() - offset; result.resize(length); - memory::copy(result.pointer(), self.data() + offset, length); + memory::copy(result.get(), self.data() + offset, length); } return result; } @@ -97,7 +97,7 @@ auto substr(rstring source, signed offset, signed length) -> string { string result; if(length < 0) length = source.size() - offset; result.resize(length); - memory::copy(result.pointer(), source.data() + offset, length); + memory::copy(result.get(), source.data() + offset, length); return result; } diff --git a/nall/varint.hpp b/nall/varint.hpp index cd45a3e7..38653997 100644 --- a/nall/varint.hpp +++ b/nall/varint.hpp @@ -26,9 +26,9 @@ struct varint { auto readvs() -> intmax_t { uintmax_t data = readvu(); - bool sign = data & 1; + bool negate = data & 1; data >>= 1; - if(sign) data = -data; + if(negate) data = ~data; return data; } @@ -43,9 +43,9 @@ struct varint { } auto writevs(intmax_t data) -> void { - bool sign = data < 0; - if(sign) data = -data; - data = (data << 1) | sign; + bool negate = data < 0; + if(negate) data = ~data; + data = (data << 1) | negate; writevu(data); } }; diff --git a/nall/windows/guid.hpp b/nall/windows/guid.hpp index da664bcc..11124b15 100644 --- a/nall/windows/guid.hpp +++ b/nall/windows/guid.hpp @@ -13,15 +13,15 @@ inline string guid() { for(unsigned n = 0; n < 256; n++) lfsr(); string output; - for(unsigned n = 0; n < 4; n++) output.append(hex<2>(lfsr())); + for(unsigned n = 0; n < 4; n++) output.append(hex(lfsr(), 2L)); output.append("-"); - for(unsigned n = 0; n < 2; n++) output.append(hex<2>(lfsr())); + for(unsigned n = 0; n < 2; n++) output.append(hex(lfsr(), 2L)); output.append("-"); - for(unsigned n = 0; n < 2; n++) output.append(hex<2>(lfsr())); + for(unsigned n = 0; n < 2; n++) output.append(hex(lfsr(), 2L)); output.append("-"); - for(unsigned n = 0; n < 2; n++) output.append(hex<2>(lfsr())); + for(unsigned n = 0; n < 2; n++) output.append(hex(lfsr(), 2L)); output.append("-"); - for(unsigned n = 0; n < 6; n++) output.append(hex<2>(lfsr())); + for(unsigned n = 0; n < 6; n++) output.append(hex(lfsr(), 2L)); return {"{", output, "}"}; } diff --git a/processor/arm/instructions-arm.cpp b/processor/arm/instructions-arm.cpp index 27d8016d..9592fe64 100644 --- a/processor/arm/instructions-arm.cpp +++ b/processor/arm/instructions-arm.cpp @@ -514,11 +514,15 @@ auto ARM::arm_op_move_multiple() { if(pre == 1 && up == 0) rn = rn - bit::count(list) * 4 + 0; //DB if(pre == 0 && up == 0) rn = rn - bit::count(list) * 4 + 4; //DA + if(writeback && l == 1) { + if(up == 1) r(n) = r(n) + bit::count(list) * 4; //IA, IB + if(up == 0) r(n) = r(n) - bit::count(list) * 4; //DA, DB + } + Processor::Mode pmode = mode(); bool usr = false; if(s && l == 1 && (list & 0x8000) == 0) usr = true; if(s && l == 0) usr = true; - if(usr) processor.setMode(Processor::Mode::USR); unsigned sequential = Nonsequential; @@ -545,7 +549,7 @@ auto ARM::arm_op_move_multiple() { pipeline.nonsequential = true; } - if(writeback) { + if(writeback && l == 0) { if(up == 1) r(n) = r(n) + bit::count(list) * 4; //IA, IB if(up == 0) r(n) = r(n) - bit::count(list) * 4; //DA, DB } diff --git a/ruby/input/joypad/udev.cpp b/ruby/input/joypad/udev.cpp index d297545f..941175c0 100644 --- a/ruby/input/joypad/udev.cpp +++ b/ruby/input/joypad/udev.cpp @@ -107,7 +107,7 @@ struct InputJoypadUdev { play.type = EV_FF; play.code = jp.effectID; play.value = enable; - write(jp.fd, &play, sizeof(input_event)); + auto unused = write(jp.fd, &play, sizeof(input_event)); return true; } diff --git a/sfc/GNUmakefile b/sfc/GNUmakefile index e418158b..e83d7619 100644 --- a/sfc/GNUmakefile +++ b/sfc/GNUmakefile @@ -2,7 +2,7 @@ sfc_objects := sfc-interface sfc-system sfc-controller sfc_objects += sfc-cartridge sfc-cheat sfc_objects += sfc-memory sfc-cpu sfc-smp sfc-dsp sfc-ppu sfc_objects += sfc-satellaviewbase -sfc_objects += sfc-icd2 sfc-bsx sfc-nss sfc-event +sfc_objects += sfc-icd2 sfc-mcc sfc-nss sfc-event sfc_objects += sfc-sa1 sfc-superfx sfc_objects += sfc-armdsp sfc-hitachidsp sfc-necdsp sfc_objects += sfc-epsonrtc sfc-sharprtc @@ -47,7 +47,7 @@ obj/sfc-ppu.o: $(sfcppu)/ppu.cpp $(call rwildcard,$(sfcppu)/) obj/sfc-satellaviewbase.o: $(sfc)/base/satellaview/satellaview.cpp $(call rwildcard,$(sfc)/base/satellaview/) obj/sfc-icd2.o: $(sfc)/chip/icd2/icd2.cpp $(call rwildcard,$(sfc)/chip/icd2/) -obj/sfc-bsx.o: $(sfc)/chip/bsx/bsx.cpp $(call rwildcard,$(sfc)/chip/bsx/) +obj/sfc-mcc.o: $(sfc)/chip/mcc/mcc.cpp $(call rwildcard,$(sfc)/chip/mcc/) obj/sfc-nss.o: $(sfc)/chip/nss/nss.cpp $(call rwildcard,$(sfc)/chip/nss/) obj/sfc-event.o: $(sfc)/chip/event/event.cpp $(call rwildcard,$(sfc)/chip/event/) diff --git a/sfc/base/satellaview/satellaview.cpp b/sfc/base/satellaview/satellaview.cpp index 947956f2..64c245f7 100644 --- a/sfc/base/satellaview/satellaview.cpp +++ b/sfc/base/satellaview/satellaview.cpp @@ -5,10 +5,10 @@ namespace SuperFamicom { SatellaviewBaseUnit satellaviewbaseunit; -void SatellaviewBaseUnit::init() { +auto SatellaviewBaseUnit::init() -> void { } -void SatellaviewBaseUnit::load() { +auto SatellaviewBaseUnit::load() -> void { bus.map( {&SatellaviewBaseUnit::read, &satellaviewbaseunit}, {&SatellaviewBaseUnit::write, &satellaviewbaseunit}, @@ -21,17 +21,17 @@ void SatellaviewBaseUnit::load() { ); } -void SatellaviewBaseUnit::unload() { +auto SatellaviewBaseUnit::unload() -> void { } -void SatellaviewBaseUnit::power() { +auto SatellaviewBaseUnit::power() -> void { } -void SatellaviewBaseUnit::reset() { +auto SatellaviewBaseUnit::reset() -> void { memset(®s, 0x00, sizeof regs); } -uint8 SatellaviewBaseUnit::read(unsigned addr) { +auto SatellaviewBaseUnit::read(unsigned addr) -> uint8 { addr &= 0xffff; switch(addr) { @@ -89,7 +89,7 @@ uint8 SatellaviewBaseUnit::read(unsigned addr) { return cpu.regs.mdr; } -void SatellaviewBaseUnit::write(unsigned addr, uint8 data) { +auto SatellaviewBaseUnit::write(unsigned addr, uint8 data) -> void { addr &= 0xffff; switch(addr) { diff --git a/sfc/base/satellaview/satellaview.hpp b/sfc/base/satellaview/satellaview.hpp index 2fb7ddde..17ba4091 100644 --- a/sfc/base/satellaview/satellaview.hpp +++ b/sfc/base/satellaview/satellaview.hpp @@ -1,12 +1,12 @@ struct SatellaviewBaseUnit : Memory { - void init(); - void load(); - void unload(); - void power(); - void reset(); + auto init() -> void; + auto load() -> void; + auto unload() -> void; + auto power() -> void; + auto reset() -> void; - uint8 read(unsigned addr); - void write(unsigned addr, uint8 data); + auto read(unsigned addr) -> uint8; + auto write(unsigned addr, uint8 data) -> void; private: struct { diff --git a/sfc/cartridge/cartridge.cpp b/sfc/cartridge/cartridge.cpp index f427233a..2acbc99a 100644 --- a/sfc/cartridge/cartridge.cpp +++ b/sfc/cartridge/cartridge.cpp @@ -7,7 +7,7 @@ namespace SuperFamicom { #include "serialization.cpp" Cartridge cartridge; -string Cartridge::title() { +auto Cartridge::title() -> string { if(information.title.gameBoy.empty() == false) { return {information.title.cartridge, " + ", information.title.gameBoy}; } @@ -27,27 +27,28 @@ string Cartridge::title() { return information.title.cartridge; } -void Cartridge::load() { - region = Region::NTSC; +auto Cartridge::load() -> void { + _region = Region::NTSC; - has_gb_slot = false; - has_bs_cart = false; - has_bs_slot = false; - has_st_slots = false; - has_nss_dip = false; - has_event = false; - has_sa1 = false; - has_superfx = false; - has_armdsp = false; - has_hitachidsp = false; - has_necdsp = false; - has_epsonrtc = false; - has_sharprtc = false; - has_spc7110 = false; - has_sdd1 = false; - has_obc1 = false; - has_hsu1 = false; - has_msu1 = false; + hasICD2 = false; + hasMCC = false; + hasNSSDIP = false; + hasEvent = false; + hasSA1 = false; + hasSuperFX = false; + hasARMDSP = false; + hasHitachiDSP = false; + hasNECDSP = false; + hasEpsonRTC = false; + hasSharpRTC = false; + hasSPC7110 = false; + hasSDD1 = false; + hasOBC1 = false; + hasMSU1 = false; + + hasSuperGameBoySlot = false; + hasSatellaviewSlot = false; + hasSufamiTurboSlots = false; information.markup.cartridge = ""; information.markup.gameBoy = ""; @@ -62,24 +63,24 @@ void Cartridge::load() { information.title.sufamiTurboB = ""; interface->loadRequest(ID::Manifest, "manifest.bml"); - parse_markup(information.markup.cartridge); + parseMarkup(information.markup.cartridge); //Super Game Boy - if(cartridge.has_gb_slot()) { - sha256 = Hash::SHA256(GameBoy::cartridge.romdata, GameBoy::cartridge.romsize).digest(); + if(cartridge.hasICD2()) { + _sha256 = Hash::SHA256(GameBoy::cartridge.romdata, GameBoy::cartridge.romsize).digest(); } //Broadcast Satellaview - else if(cartridge.has_bs_cart() && cartridge.has_bs_slot()) { - sha256 = Hash::SHA256(satellaviewcartridge.memory.data(), satellaviewcartridge.memory.size()).digest(); + else if(cartridge.hasMCC() && cartridge.hasSatellaviewSlot()) { + _sha256 = Hash::SHA256(satellaviewcartridge.memory.data(), satellaviewcartridge.memory.size()).digest(); } //Sufami Turbo - else if(cartridge.has_st_slots()) { + else if(cartridge.hasSufamiTurboSlots()) { Hash::SHA256 sha; sha.data(sufamiturboA.rom.data(), sufamiturboA.rom.size()); sha.data(sufamiturboB.rom.data(), sufamiturboB.rom.size()); - sha256 = sha.digest(); + _sha256 = sha.digest(); } //Super Famicom @@ -87,7 +88,7 @@ void Cartridge::load() { Hash::SHA256 sha; //hash each ROM image that exists; any with size() == 0 is ignored by sha256_chunk() sha.data(rom.data(), rom.size()); - sha.data(bsxcartridge.rom.data(), bsxcartridge.rom.size()); + sha.data(mcc.rom.data(), mcc.rom.size()); sha.data(sa1.rom.data(), sa1.rom.size()); sha.data(superfx.rom.data(), superfx.rom.size()); sha.data(hitachidsp.rom.data(), hitachidsp.rom.size()); @@ -103,17 +104,17 @@ void Cartridge::load() { buffer = necdsp.firmware(); sha.data(buffer.data(), buffer.size()); //finalize hash - sha256 = sha.digest(); + _sha256 = sha.digest(); } rom.write_protect(true); ram.write_protect(false); system.load(); - loaded = true; + _loaded = true; } -void Cartridge::load_super_game_boy() { +auto Cartridge::loadSuperGameBoy() -> void { interface->loadRequest(ID::SuperGameBoyManifest, "manifest.bml"); auto document = BML::unserialize(information.markup.gameBoy); information.title.gameBoy = document["information/title"].text(); @@ -129,7 +130,7 @@ void Cartridge::load_super_game_boy() { if(auto name = ram["name"].text()) memory.append({ID::SuperGameBoyRAM, name}); } -void Cartridge::load_satellaview() { +auto Cartridge::loadSatellaview() -> void { interface->loadRequest(ID::SatellaviewManifest, "manifest.bml"); auto document = BML::unserialize(information.markup.satellaview); information.title.satellaview = document["information/title"].text(); @@ -145,7 +146,7 @@ void Cartridge::load_satellaview() { } } -void Cartridge::load_sufami_turbo_a() { +auto Cartridge::loadSufamiTurboA() -> void { interface->loadRequest(ID::SufamiTurboSlotAManifest, "manifest.bml"); auto document = BML::unserialize(information.markup.sufamiTurboA); information.title.sufamiTurboA = document["information/title"].text(); @@ -171,7 +172,7 @@ void Cartridge::load_sufami_turbo_a() { } } -void Cartridge::load_sufami_turbo_b() { +auto Cartridge::loadSufamiTurboB() -> void { interface->loadRequest(ID::SufamiTurboSlotBManifest, "manifest.bml"); auto document = BML::unserialize(information.markup.sufamiTurboB); information.title.sufamiTurboB = document["information/title"].text(); @@ -193,23 +194,15 @@ void Cartridge::load_sufami_turbo_b() { } } -void Cartridge::unload() { - if(loaded == false) return; +auto Cartridge::unload() -> void { + if(_loaded) { + system.unload(); + rom.reset(); + ram.reset(); - system.unload(); - rom.reset(); - ram.reset(); - - loaded = false; - memory.reset(); -} - -Cartridge::Cartridge() { - loaded = false; -} - -Cartridge::~Cartridge() { - unload(); + _loaded = false; + memory.reset(); + } } } diff --git a/sfc/cartridge/cartridge.hpp b/sfc/cartridge/cartridge.hpp index 9160ea0d..5493f522 100644 --- a/sfc/cartridge/cartridge.hpp +++ b/sfc/cartridge/cartridge.hpp @@ -1,54 +1,42 @@ struct Cartridge : property { - enum class Region : unsigned { - NTSC, - PAL, - }; - - enum class Slot : unsigned { - Base, - Bsx, - SufamiTurbo, - SufamiTurboA, - SufamiTurboB, - GameBoy, - }; + enum class Region : unsigned { NTSC, PAL }; MappedRAM rom; MappedRAM ram; - readonly loaded; - readonly sha256; + auto loaded() const -> bool { return _loaded; } + auto sha256() const -> string { return _sha256; } + auto region() const -> Region { return _region; } - readonly region; + readonly hasICD2; + readonly hasMCC; + readonly hasNSSDIP; + readonly hasEvent; + readonly hasSA1; + readonly hasSuperFX; + readonly hasARMDSP; + readonly hasHitachiDSP; + readonly hasNECDSP; + readonly hasEpsonRTC; + readonly hasSharpRTC; + readonly hasSPC7110; + readonly hasSDD1; + readonly hasOBC1; + readonly hasMSU1; - readonly has_gb_slot; - readonly has_bs_cart; - readonly has_bs_slot; - readonly has_st_slots; - readonly has_nss_dip; - readonly has_event; - readonly has_sa1; - readonly has_superfx; - readonly has_armdsp; - readonly has_hitachidsp; - readonly has_necdsp; - readonly has_epsonrtc; - readonly has_sharprtc; - readonly has_spc7110; - readonly has_sdd1; - readonly has_obc1; - readonly has_hsu1; - readonly has_msu1; + readonly hasSuperGameBoySlot; + readonly hasSatellaviewSlot; + readonly hasSufamiTurboSlots; struct Mapping { function reader; function writer; string addr; - unsigned size; - unsigned base; - unsigned mask; + unsigned size = 0; + unsigned base = 0; + unsigned mask = 0; - Mapping(); + Mapping() = default; Mapping(const function&, const function&); Mapping(SuperFamicom::Memory&); }; @@ -78,45 +66,50 @@ struct Cartridge : property { } title; } information; - string title(); + Cartridge() = default; + ~Cartridge() { unload(); } - void load(); - void unload(); + auto title() -> string; - void serialize(serializer&); - Cartridge(); - ~Cartridge(); + auto load() -> void; + auto unload() -> void; + + auto serialize(serializer&) -> void; private: - void load_super_game_boy(); - void load_satellaview(); - void load_sufami_turbo_a(); - void load_sufami_turbo_b(); - - void parse_markup(const char*); - void parse_markup_map(Mapping&, Markup::Node); - void parse_markup_memory(MappedRAM&, Markup::Node, unsigned id, bool writable); - - void parse_markup_cartridge(Markup::Node); - void parse_markup_icd2(Markup::Node); - void parse_markup_bsx(Markup::Node); - void parse_markup_satellaview(Markup::Node); - void parse_markup_sufamiturbo(Markup::Node, bool slot); - void parse_markup_nss(Markup::Node); - void parse_markup_event(Markup::Node); - void parse_markup_sa1(Markup::Node); - void parse_markup_superfx(Markup::Node); - void parse_markup_armdsp(Markup::Node); - void parse_markup_hitachidsp(Markup::Node, unsigned roms); - void parse_markup_necdsp(Markup::Node); - void parse_markup_epsonrtc(Markup::Node); - void parse_markup_sharprtc(Markup::Node); - void parse_markup_spc7110(Markup::Node); - void parse_markup_sdd1(Markup::Node); - void parse_markup_obc1(Markup::Node); - void parse_markup_msu1(Markup::Node); - + auto loadSuperGameBoy() -> void; + auto loadSatellaview() -> void; + auto loadSufamiTurboA() -> void; + auto loadSufamiTurboB() -> void; friend class Interface; + + //markup.cpp + auto parseMarkup(const string&) -> void; + auto parseMarkupMap(Mapping&, Markup::Node) -> void; + auto parseMarkupMemory(MappedRAM&, Markup::Node, unsigned id, bool writable) -> void; + + auto parseMarkupCartridge(Markup::Node) -> void; + auto parseMarkupICD2(Markup::Node) -> void; + auto parseMarkupMCC(Markup::Node) -> void; + auto parseMarkupSatellaview(Markup::Node) -> void; + auto parseMarkupSufamiTurbo(Markup::Node, bool slot) -> void; + auto parseMarkupNSS(Markup::Node) -> void; + auto parseMarkupEvent(Markup::Node) -> void; + auto parseMarkupSA1(Markup::Node) -> void; + auto parseMarkupSuperFX(Markup::Node) -> void; + auto parseMarkupARMDSP(Markup::Node) -> void; + auto parseMarkupHitachiDSP(Markup::Node, unsigned roms) -> void; + auto parseMarkupNECDSP(Markup::Node) -> void; + auto parseMarkupEpsonRTC(Markup::Node) -> void; + auto parseMarkupSharpRTC(Markup::Node) -> void; + auto parseMarkupSPC7110(Markup::Node) -> void; + auto parseMarkupSDD1(Markup::Node) -> void; + auto parseMarkupOBC1(Markup::Node) -> void; + auto parseMarkupMSU1(Markup::Node) -> void; + + bool _loaded = false; + string _sha256; + Region _region = Region::NTSC; }; extern Cartridge cartridge; diff --git a/sfc/cartridge/markup.cpp b/sfc/cartridge/markup.cpp index 4f890c3f..f76da21d 100644 --- a/sfc/cartridge/markup.cpp +++ b/sfc/cartridge/markup.cpp @@ -1,44 +1,52 @@ #ifdef CARTRIDGE_CPP -void Cartridge::parse_markup(const char* markup) { +Cartridge::Mapping::Mapping(SuperFamicom::Memory& memory) { + this->reader = {&SuperFamicom::Memory::read, &memory}; + this->writer = {&SuperFamicom::Memory::write, &memory}; +} + +Cartridge::Mapping::Mapping(const function& reader, const function& writer) { + this->reader = reader; + this->writer = writer; +} + +auto Cartridge::parseMarkup(const string& markup) -> void { auto document = BML::unserialize(markup); information.title.cartridge = document["information/title"].text(); auto cartridge = document["cartridge"]; - region = cartridge["region"].text() != "PAL" ? Region::NTSC : Region::PAL; + _region = cartridge["region"].text() != "PAL" ? Region::NTSC : Region::PAL; mapping.reset(); - parse_markup_cartridge(cartridge); - parse_markup_icd2(cartridge["icd2"]); - parse_markup_bsx(cartridge["bsx"]); - parse_markup_satellaview(cartridge["satellaview"]); - parse_markup_sufamiturbo(cartridge["sufamiturbo[0]"], 0); - parse_markup_sufamiturbo(cartridge["sufamiturbo[1]"], 1); - parse_markup_nss(cartridge["nss"]); - parse_markup_event(cartridge["event"]); - parse_markup_sa1(cartridge["sa1"]); - parse_markup_superfx(cartridge["superfx"]); - parse_markup_armdsp(cartridge["armdsp"]); - parse_markup_hitachidsp(cartridge["hitachidsp"], cartridge["board/type"].text().match("2DC*") ? 2 : 1); - parse_markup_necdsp(cartridge["necdsp"]); - parse_markup_epsonrtc(cartridge["epsonrtc"]); - parse_markup_sharprtc(cartridge["sharprtc"]); - parse_markup_spc7110(cartridge["spc7110"]); - parse_markup_sdd1(cartridge["sdd1"]); - parse_markup_obc1(cartridge["obc1"]); - parse_markup_msu1(cartridge["msu1"]); + if(auto node = cartridge) parseMarkupCartridge(node); + if(auto node = cartridge["icd2"]) parseMarkupICD2(node); + if(auto node = cartridge["mcc"]) parseMarkupMCC(node); + if(auto node = cartridge["satellaview"]) parseMarkupSatellaview(node); + if(auto node = cartridge.find("sufamiturbo")) if(node(0)) parseMarkupSufamiTurbo(node(0), 0); + if(auto node = cartridge.find("sufamiturbo")) if(node(1)) parseMarkupSufamiTurbo(node(1), 1); + if(auto node = cartridge["nss"]) parseMarkupNSS(node); + if(auto node = cartridge["event"]) parseMarkupEvent(node); + if(auto node = cartridge["sa1"]) parseMarkupSA1(node); + if(auto node = cartridge["superfx"]) parseMarkupSuperFX(node); + if(auto node = cartridge["armdsp"]) parseMarkupARMDSP(node); + if(auto node = cartridge["hitachidsp"]) parseMarkupHitachiDSP(node, cartridge["board/type"].text().match("2DC*") ? 2 : 1); + if(auto node = cartridge["necdsp"]) parseMarkupNECDSP(node); + if(auto node = cartridge["epsonrtc"]) parseMarkupEpsonRTC(node); + if(auto node = cartridge["sharprtc"]) parseMarkupSharpRTC(node); + if(auto node = cartridge["spc7110"]) parseMarkupSPC7110(node); + if(auto node = cartridge["sdd1"]) parseMarkupSDD1(node); + if(auto node = cartridge["obc1"]) parseMarkupOBC1(node); + if(auto node = cartridge["msu1"]) parseMarkupMSU1(node); } -// - -void Cartridge::parse_markup_map(Mapping& m, Markup::Node map) { +auto Cartridge::parseMarkupMap(Mapping& m, Markup::Node map) -> void { m.addr = map["address"].text(); m.size = map["size"].decimal(); m.base = map["base"].decimal(); m.mask = map["mask"].decimal(); } -void Cartridge::parse_markup_memory(MappedRAM& ram, Markup::Node node, unsigned id, bool writable) { +auto Cartridge::parseMarkupMemory(MappedRAM& ram, Markup::Node node, unsigned id, bool writable) -> void { string name = node["name"].text(); unsigned size = node["size"].decimal(); ram.map(allocate(size, 0xff), size); @@ -48,34 +56,30 @@ void Cartridge::parse_markup_memory(MappedRAM& ram, Markup::Node node, unsigned } } -// - -void Cartridge::parse_markup_cartridge(Markup::Node root) { - if(!root) return; - - parse_markup_memory(rom, root["rom"], ID::ROM, false); - parse_markup_memory(ram, root["ram"], ID::RAM, true); +auto Cartridge::parseMarkupCartridge(Markup::Node root) -> void { + parseMarkupMemory(rom, root["rom"], ID::ROM, false); + parseMarkupMemory(ram, root["ram"], ID::RAM, true); for(auto node : root.find("map")) { if(node["id"].text() == "rom") { Mapping m(rom); - parse_markup_map(m, node); + parseMarkupMap(m, node); if(m.size == 0) m.size = rom.size(); mapping.append(m); } if(node["id"].text() == "ram") { Mapping m(ram); - parse_markup_map(m, node); + parseMarkupMap(m, node); if(m.size == 0) m.size = ram.size(); mapping.append(m); } } } -void Cartridge::parse_markup_icd2(Markup::Node root) { - if(!root) return; - has_gb_slot = true; +auto Cartridge::parseMarkupICD2(Markup::Node root) -> void { + hasSuperGameBoySlot = true; + hasICD2 = true; icd2.revision = max(1, root["revision"].decimal()); GameBoy::cartridge.load_empty(GameBoy::System::Revision::SuperGameBoy); @@ -87,42 +91,40 @@ void Cartridge::parse_markup_icd2(Markup::Node root) { for(auto node : root.find("map")) { if(node["id"].text() == "io") { Mapping m({&ICD2::read, &icd2}, {&ICD2::write, &icd2}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } } } -void Cartridge::parse_markup_bsx(Markup::Node root) { - if(!root) return; - has_bs_cart = true; - has_bs_slot = true; +auto Cartridge::parseMarkupMCC(Markup::Node root) -> void { + hasSatellaviewSlot = true; + hasMCC = true; interface->loadRequest(ID::Satellaview, "BS-X Satellaview", "bs"); - parse_markup_memory(bsxcartridge.rom, root["rom"], ID::BsxROM, false); - parse_markup_memory(bsxcartridge.ram, root["ram"], ID::BsxRAM, true); - parse_markup_memory(bsxcartridge.psram, root["psram"], ID::BsxPSRAM, true); + parseMarkupMemory(mcc.rom, root["rom"], ID::MCCROM, false); + parseMarkupMemory(mcc.ram, root["ram"], ID::MCCRAM, true); + parseMarkupMemory(mcc.psram, root["psram"], ID::MCCPSRAM, true); for(auto node : root.find("map")) { if(node["id"].text() == "rom" || node["id"].text() == "ram") { - Mapping m({&BSXCartridge::mcu_read, &bsxcartridge}, {&BSXCartridge::mcu_write, &bsxcartridge}); - parse_markup_map(m, node); + Mapping m({&MCC::mcu_read, &mcc}, {&MCC::mcu_write, &mcc}); + parseMarkupMap(m, node); mapping.append(m); } if(node["id"].text() == "io") { - Mapping m({&BSXCartridge::mmio_read, &bsxcartridge}, {&BSXCartridge::mmio_write, &bsxcartridge}); - parse_markup_map(m, node); + Mapping m({&MCC::mmio_read, &mcc}, {&MCC::mmio_write, &mcc}); + parseMarkupMap(m, node); mapping.append(m); } } } -void Cartridge::parse_markup_satellaview(Markup::Node root) { - if(!root) return; - has_bs_slot = true; +auto Cartridge::parseMarkupSatellaview(Markup::Node root) -> void { + hasSatellaviewSlot = true; interface->loadRequest(ID::Satellaview, "BS-X Satellaview", "bs"); @@ -131,15 +133,14 @@ void Cartridge::parse_markup_satellaview(Markup::Node root) { if(satellaviewcartridge.memory.size() == 0) continue; Mapping m(satellaviewcartridge); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } } } -void Cartridge::parse_markup_sufamiturbo(Markup::Node root, bool slot) { - if(!root) return; - has_st_slots = true; +auto Cartridge::parseMarkupSufamiTurbo(Markup::Node root, bool slot) -> void { + hasSufamiTurboSlots = true; if(slot == 0) { //load required slot A (will request slot B if slot A cartridge is linkable) @@ -153,7 +154,7 @@ void Cartridge::parse_markup_sufamiturbo(Markup::Node root, bool slot) { if(cart.rom.size() == 0) continue; Mapping m(cart.rom); - parse_markup_map(m, node); + parseMarkupMap(m, node); if(m.size == 0) m.size = cart.rom.size(); if(m.size) mapping.append(m); } @@ -162,37 +163,35 @@ void Cartridge::parse_markup_sufamiturbo(Markup::Node root, bool slot) { if(cart.ram.size() == 0) continue; Mapping m(cart.ram); - parse_markup_map(m, node); + parseMarkupMap(m, node); if(m.size == 0) m.size = cart.ram.size(); if(m.size) mapping.append(m); } } } -void Cartridge::parse_markup_nss(Markup::Node root) { - if(!root) return; - has_nss_dip = true; +auto Cartridge::parseMarkupNSS(Markup::Node root) -> void { + hasNSSDIP = true; nss.dip = interface->dipSettings(root); for(auto node : root.find("map")) { if(node["id"].text() == "io") { Mapping m({&NSS::read, &nss}, {&NSS::write, &nss}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } } } -void Cartridge::parse_markup_event(Markup::Node root) { - if(!root) return; - has_event = true; +auto Cartridge::parseMarkupEvent(Markup::Node root) -> void { + hasEvent = true; for(auto node : root.find("rom")) { unsigned id = node["id"].decimal(); if(id > 3) continue; - parse_markup_memory(event.rom[id], node, ID::EventROM0 + id, false); + parseMarkupMemory(event.rom[id], node, ID::EventROM0 + id, false); } - parse_markup_memory(event.ram, root["ram"], ID::EventRAM, true); + parseMarkupMemory(event.ram, root["ram"], ID::EventRAM, true); event.board = Event::Board::CampusChallenge92; if(root["name"].text() == "Campus Challenge '92") event.board = Event::Board::CampusChallenge92; @@ -206,105 +205,102 @@ void Cartridge::parse_markup_event(Markup::Node root) { for(auto node : root.find("map")) { if(node["id"].text() == "rom") { Mapping m({&Event::rom_read, &event}, [](unsigned, uint8) {}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } if(node["id"].text() == "ram") { Mapping m({&Event::ram_read, &event}, {&Event::ram_write, &event}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } if(node["id"].text() == "dr") { Mapping m([](unsigned) -> uint8 { return cpu.regs.mdr; }, {&Event::dr, &event}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } if(node["id"].text() == "sr") { Mapping m({&Event::sr, &event}, [](unsigned, uint8) {}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } } } -void Cartridge::parse_markup_sa1(Markup::Node root) { - if(!root) return; - has_sa1 = true; +auto Cartridge::parseMarkupSA1(Markup::Node root) -> void { + hasSA1 = true; auto rom = root.find("rom"); auto ram = root.find("ram"); - parse_markup_memory(sa1.rom, rom(0), ID::SA1ROM, false); - parse_markup_memory(sa1.bwram, ram(0), ID::SA1BWRAM, true); - parse_markup_memory(sa1.iram, ram(1), ID::SA1IRAM, true); + parseMarkupMemory(sa1.rom, rom(0), ID::SA1ROM, false); + parseMarkupMemory(sa1.bwram, ram(0), ID::SA1BWRAM, true); + parseMarkupMemory(sa1.iram, ram(1), ID::SA1IRAM, true); for(auto node : root.find("map")) { if(node["id"].text() == "io") { Mapping m({&SA1::mmio_read, &sa1}, {&SA1::mmio_write, &sa1}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } if(node["id"].text() == "rom") { Mapping m({&SA1::mmcrom_read, &sa1}, {&SA1::mmcrom_write, &sa1}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } if(node["id"].text() == "bwram") { Mapping m({&SA1::mmcbwram_read, &sa1}, {&SA1::mmcbwram_write, &sa1}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } if(node["id"].text() == "iram") { Mapping m(sa1.cpuiram); - parse_markup_map(m, node); + parseMarkupMap(m, node); if(m.size == 0) m.size = sa1.cpuiram.size(); mapping.append(m); } } } -void Cartridge::parse_markup_superfx(Markup::Node root) { - if(!root) return; - has_superfx = true; +auto Cartridge::parseMarkupSuperFX(Markup::Node root) -> void { + hasSuperFX = true; auto rom = root.find("rom"); auto ram = root.find("ram"); - parse_markup_memory(superfx.rom, rom(0), ID::SuperFXROM, false); - parse_markup_memory(superfx.ram, ram(0), ID::SuperFXRAM, true); + parseMarkupMemory(superfx.rom, rom(0), ID::SuperFXROM, false); + parseMarkupMemory(superfx.ram, ram(0), ID::SuperFXRAM, true); for(auto node : root.find("map")) { if(node["id"].text() == "io") { Mapping m({&SuperFX::mmio_read, &superfx}, {&SuperFX::mmio_write, &superfx}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } if(node["id"].text() == "rom") { Mapping m(superfx.cpurom); - parse_markup_map(m, node); + parseMarkupMap(m, node); if(m.size == 0) m.size = superfx.rom.size(); mapping.append(m); } if(node["id"].text() == "ram") { Mapping m(superfx.cpuram); - parse_markup_map(m, node); + parseMarkupMap(m, node); if(m.size == 0) m.size = superfx.ram.size(); mapping.append(m); } } } -void Cartridge::parse_markup_armdsp(Markup::Node root) { - if(!root) return; - has_armdsp = true; +auto Cartridge::parseMarkupARMDSP(Markup::Node root) -> void { + hasARMDSP = true; auto rom = root.find("rom"); auto ram = root.find("ram"); @@ -323,21 +319,20 @@ void Cartridge::parse_markup_armdsp(Markup::Node root) { for(auto node : root.find("map")) { if(node["id"].text() == "io") { Mapping m({&ArmDSP::mmio_read, &armdsp}, {&ArmDSP::mmio_write, &armdsp}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } } } -void Cartridge::parse_markup_hitachidsp(Markup::Node root, unsigned roms) { - if(!root) return; - has_hitachidsp = true; +auto Cartridge::parseMarkupHitachiDSP(Markup::Node root, unsigned roms) -> void { + hasHitachiDSP = true; auto rom = root.find("rom"); auto ram = root.find("ram"); - parse_markup_memory(hitachidsp.rom, rom(0), ID::HitachiDSPROM, false); - parse_markup_memory(hitachidsp.ram, ram(0), ID::HitachiDSPRAM, true); + parseMarkupMemory(hitachidsp.rom, rom(0), ID::HitachiDSPROM, false); + parseMarkupMemory(hitachidsp.ram, ram(0), ID::HitachiDSPRAM, true); for(auto& word : hitachidsp.dataROM) word = 0x000000; for(auto& word : hitachidsp.dataRAM) word = 0x00; @@ -357,29 +352,28 @@ void Cartridge::parse_markup_hitachidsp(Markup::Node root, unsigned roms) { for(auto node : root.find("map")) { if(node["id"].text() == "io") { Mapping m({&HitachiDSP::dsp_read, &hitachidsp}, {&HitachiDSP::dsp_write, &hitachidsp}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } if(node["id"].text() == "rom") { Mapping m({&HitachiDSP::rom_read, &hitachidsp}, {&HitachiDSP::rom_write, &hitachidsp}); - parse_markup_map(m, node); + parseMarkupMap(m, node); if(m.size == 0) m.size = hitachidsp.rom.size(); mapping.append(m); } if(node["id"].text() == "ram") { Mapping m({&HitachiDSP::ram_read, &hitachidsp}, {&HitachiDSP::ram_write, &hitachidsp}); - parse_markup_map(m, node); + parseMarkupMap(m, node); if(m.size == 0) m.size = hitachidsp.ram.size(); mapping.append(m); } } } -void Cartridge::parse_markup_necdsp(Markup::Node root) { - if(!root) return; - has_necdsp = true; +auto Cartridge::parseMarkupNECDSP(Markup::Node root) -> void { + hasNECDSP = true; for(auto& word : necdsp.programROM) word = 0x000000; for(auto& word : necdsp.dataROM) word = 0x0000; @@ -420,22 +414,21 @@ void Cartridge::parse_markup_necdsp(Markup::Node root) { for(auto node : root.find("map")) { if(node["id"].text() == "io") { Mapping m({&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); necdsp.Select = node["select"].decimal(); } if(node["id"].text() == "ram") { Mapping m({&NECDSP::ram_read, &necdsp}, {&NECDSP::ram_write, &necdsp}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } } } -void Cartridge::parse_markup_epsonrtc(Markup::Node root) { - if(!root) return; - has_epsonrtc = true; +auto Cartridge::parseMarkupEpsonRTC(Markup::Node root) -> void { + hasEpsonRTC = true; string name = root["ram/name"].text(); interface->loadRequest(ID::EpsonRTC, name); @@ -444,15 +437,14 @@ void Cartridge::parse_markup_epsonrtc(Markup::Node root) { for(auto node : root.find("map")) { if(node["id"].text() == "io") { Mapping m({&EpsonRTC::read, &epsonrtc}, {&EpsonRTC::write, &epsonrtc}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } } } -void Cartridge::parse_markup_sharprtc(Markup::Node root) { - if(!root) return; - has_sharprtc = true; +auto Cartridge::parseMarkupSharpRTC(Markup::Node root) -> void { + hasSharpRTC = true; string name = root["ram/name"].text(); interface->loadRequest(ID::SharpRTC, name); @@ -461,117 +453,97 @@ void Cartridge::parse_markup_sharprtc(Markup::Node root) { for(auto node : root.find("map")) { if(node["id"].text() == "io") { Mapping m({&SharpRTC::read, &sharprtc}, {&SharpRTC::write, &sharprtc}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } } } -void Cartridge::parse_markup_spc7110(Markup::Node root) { - if(!root) return; - has_spc7110 = true; +auto Cartridge::parseMarkupSPC7110(Markup::Node root) -> void { + hasSPC7110 = true; auto rom = root.find("rom"); auto ram = root.find("ram"); - parse_markup_memory(spc7110.prom, rom(0), ID::SPC7110PROM, false); - parse_markup_memory(spc7110.drom, rom(1), ID::SPC7110DROM, false); - parse_markup_memory(spc7110.ram, ram(0), ID::SPC7110RAM, true); + parseMarkupMemory(spc7110.prom, rom(0), ID::SPC7110PROM, false); + parseMarkupMemory(spc7110.drom, rom(1), ID::SPC7110DROM, false); + parseMarkupMemory(spc7110.ram, ram(0), ID::SPC7110RAM, true); for(auto node : root.find("map")) { if(node["id"].text() == "io") { Mapping m({&SPC7110::read, &spc7110}, {&SPC7110::write, &spc7110}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } if(node["id"].text() == "rom") { Mapping m({&SPC7110::mcurom_read, &spc7110}, {&SPC7110::mcurom_write, &spc7110}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } if(node["id"].text() == "ram") { Mapping m({&SPC7110::mcuram_read, &spc7110}, {&SPC7110::mcuram_write, &spc7110}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } } } -void Cartridge::parse_markup_sdd1(Markup::Node root) { - if(!root) return; - has_sdd1 = true; +auto Cartridge::parseMarkupSDD1(Markup::Node root) -> void { + hasSDD1 = true; auto rom = root.find("rom"); auto ram = root.find("ram"); - parse_markup_memory(sdd1.rom, rom(0), ID::SDD1ROM, false); - parse_markup_memory(sdd1.ram, ram(0), ID::SDD1RAM, true); + parseMarkupMemory(sdd1.rom, rom(0), ID::SDD1ROM, false); + parseMarkupMemory(sdd1.ram, ram(0), ID::SDD1RAM, true); for(auto node : root.find("map")) { if(node["id"].text() == "io") { Mapping m({&SDD1::read, &sdd1}, {&SDD1::write, &sdd1}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } if(node["id"].text() == "rom") { Mapping m({&SDD1::mcurom_read, &sdd1}, {&SDD1::mcurom_write, &sdd1}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } if(node["id"].text() == "ram") { Mapping m({&SDD1::mcuram_read, &sdd1}, {&SDD1::mcuram_write, &sdd1}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } } } -void Cartridge::parse_markup_obc1(Markup::Node root) { - if(!root) return; - has_obc1 = true; +auto Cartridge::parseMarkupOBC1(Markup::Node root) -> void { + hasOBC1 = true; - parse_markup_memory(obc1.ram, root["ram"], ID::OBC1RAM, true); + parseMarkupMemory(obc1.ram, root["ram"], ID::OBC1RAM, true); for(auto node : root.find("map")) { if(node["id"].text() == "io") { Mapping m({&OBC1::read, &obc1}, {&OBC1::write, &obc1}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } } } -void Cartridge::parse_markup_msu1(Markup::Node root) { - if(!root) return; - has_msu1 = true; +auto Cartridge::parseMarkupMSU1(Markup::Node root) -> void { + hasMSU1 = true; for(auto node : root.find("map")) { if(node["id"].text() == "io") { Mapping m({&MSU1::mmio_read, &msu1}, {&MSU1::mmio_write, &msu1}); - parse_markup_map(m, node); + parseMarkupMap(m, node); mapping.append(m); } } } -Cartridge::Mapping::Mapping() { - size = base = mask = 0; -} - -Cartridge::Mapping::Mapping(SuperFamicom::Memory& memory) { - reader = {&SuperFamicom::Memory::read, &memory}; - writer = {&SuperFamicom::Memory::write, &memory}; - size = base = mask = 0; -} - -Cartridge::Mapping::Mapping(const function& reader, const function& writer) { - this->reader = reader; - this->writer = writer; - size = base = mask = 0; -} - #endif diff --git a/sfc/cartridge/serialization.cpp b/sfc/cartridge/serialization.cpp index 07948643..c95bfe02 100644 --- a/sfc/cartridge/serialization.cpp +++ b/sfc/cartridge/serialization.cpp @@ -1,6 +1,6 @@ #ifdef CARTRIDGE_CPP -void Cartridge::serialize(serializer& s) { +auto Cartridge::serialize(serializer& s) -> void { s.array(ram.data(), ram.size()); } diff --git a/sfc/chip/armdsp/serialization.cpp b/sfc/chip/armdsp/serialization.cpp index 68531baa..6927bca2 100644 --- a/sfc/chip/armdsp/serialization.cpp +++ b/sfc/chip/armdsp/serialization.cpp @@ -2,7 +2,7 @@ nall::vector ArmDSP::firmware() { nall::vector buffer; - if(cartridge.has_armdsp() == false) return buffer; + if(!cartridge.hasARMDSP()) return buffer; buffer.reserve(128 * 1024 + 32 * 1024); for(unsigned n = 0; n < 128 * 1024; n++) buffer.append(programROM[n]); for(unsigned n = 0; n < 32 * 1024; n++) buffer.append(dataROM[n]); diff --git a/sfc/chip/bsx/bsx.hpp b/sfc/chip/bsx/bsx.hpp deleted file mode 100644 index be31ea5b..00000000 --- a/sfc/chip/bsx/bsx.hpp +++ /dev/null @@ -1,34 +0,0 @@ -struct BSXCartridge { - MappedRAM rom; - MappedRAM ram; - MappedRAM psram; - - void init(); - void load(); - void unload(); - void power(); - void reset(); - - uint8 memory_access(bool write, Memory& memory, unsigned addr, uint8 data); - uint8 memory_read(Memory& memory, unsigned addr); - void memory_write(Memory& memory, unsigned addr, uint8 data); - - uint8 mcu_access(bool write, unsigned addr, uint8 data = 0x00); - uint8 mcu_read(unsigned addr); - void mcu_write(unsigned addr, uint8 data); - - uint8 mmio_read(unsigned addr); - void mmio_write(unsigned addr, uint8 data); - void mmio_commit(); - - void serialize(serializer&); - -private: - uint8 r[16]; - bool r00, r01, r02, r03; - bool r04, r05, r06, r07; - bool r08, r09, r0a, r0b; - bool r0c, r0d, r0e, r0f; -}; - -extern BSXCartridge bsxcartridge; diff --git a/sfc/chip/chip.hpp b/sfc/chip/chip.hpp index 9e4b13f7..076dfec5 100644 --- a/sfc/chip/chip.hpp +++ b/sfc/chip/chip.hpp @@ -1,10 +1,10 @@ struct Coprocessor : Thread { - alwaysinline void step(unsigned clocks); - alwaysinline void synchronize_cpu(); + alwaysinline auto step(unsigned clocks) -> void; + alwaysinline auto synchronize_cpu() -> void; }; #include -#include +#include #include #include @@ -24,10 +24,10 @@ struct Coprocessor : Thread { #include -void Coprocessor::step(unsigned clocks) { +auto Coprocessor::step(unsigned clocks) -> void { clock += clocks * (uint64)cpu.frequency; } -void Coprocessor::synchronize_cpu() { +auto Coprocessor::synchronize_cpu() -> void { if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); } diff --git a/sfc/chip/hitachidsp/serialization.cpp b/sfc/chip/hitachidsp/serialization.cpp index 050e01b6..aa867a0b 100644 --- a/sfc/chip/hitachidsp/serialization.cpp +++ b/sfc/chip/hitachidsp/serialization.cpp @@ -2,7 +2,7 @@ vector HitachiDSP::firmware() { vector buffer; - if(cartridge.has_hitachidsp() == false) return buffer; + if(!cartridge.hasHitachiDSP()) return buffer; buffer.reserve(1024 * 3); for(unsigned n = 0; n < 1024; n++) { buffer.append(dataROM[n] >> 0); diff --git a/sfc/chip/bsx/bsx.cpp b/sfc/chip/mcc/mcc.cpp similarity index 80% rename from sfc/chip/bsx/bsx.cpp rename to sfc/chip/mcc/mcc.cpp index 567026ab..61d683a5 100644 --- a/sfc/chip/bsx/bsx.cpp +++ b/sfc/chip/mcc/mcc.cpp @@ -1,50 +1,50 @@ #include -#define BSX_CPP +#define MCC_CPP namespace SuperFamicom { #include "serialization.cpp" -BSXCartridge bsxcartridge; +MCC mcc; -void BSXCartridge::init() { +auto MCC::init() -> void { } -void BSXCartridge::load() { +auto MCC::load() -> void { } -void BSXCartridge::unload() { +auto MCC::unload() -> void { rom.reset(); ram.reset(); psram.reset(); } -void BSXCartridge::power() { +auto MCC::power() -> void { } -void BSXCartridge::reset() { +auto MCC::reset() -> void { for(unsigned i = 0; i < 16; i++) r[i] = 0x00; r[0x07] = 0x80; r[0x08] = 0x80; mmio_commit(); } -uint8 BSXCartridge::memory_access(bool write, Memory& memory, unsigned addr, uint8 data) { +auto MCC::memory_access(bool write, Memory& memory, unsigned addr, uint8 data) -> uint8 { if(write == 0) return memory_read(memory, addr); memory_write(memory, addr, data); } -uint8 BSXCartridge::memory_read(Memory& memory, unsigned addr) { +auto MCC::memory_read(Memory& memory, unsigned addr) -> uint8 { addr = bus.mirror(addr, memory.size()); return memory.read(addr); } -void BSXCartridge::memory_write(Memory& memory, unsigned addr, uint8 data) { +auto MCC::memory_write(Memory& memory, unsigned addr, uint8 data) -> void { addr = bus.mirror(addr, memory.size()); return memory.write(addr, data); } //mcu_access() allows mcu_read() and mcu_write() to share decoding logic -uint8 BSXCartridge::mcu_access(bool write, unsigned addr, uint8 data) { +auto MCC::mcu_access(bool write, unsigned addr, uint8 data) -> uint8 { if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff if(r07 == 1) { addr = ((addr & 0x1f0000) >> 1) | (addr & 0x7fff); @@ -90,15 +90,15 @@ uint8 BSXCartridge::mcu_access(bool write, unsigned addr, uint8 data) { return cpu.regs.mdr; } -uint8 BSXCartridge::mcu_read(unsigned addr) { +auto MCC::mcu_read(unsigned addr) -> uint8 { return mcu_access(0, addr); } -void BSXCartridge::mcu_write(unsigned addr, uint8 data) { +auto MCC::mcu_write(unsigned addr, uint8 data) -> void { mcu_access(1, addr, data); } -uint8 BSXCartridge::mmio_read(unsigned addr) { +auto MCC::mmio_read(unsigned addr) -> uint8 { if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000 uint8 n = (addr >> 16) & 15; return r[n]; @@ -111,7 +111,7 @@ uint8 BSXCartridge::mmio_read(unsigned addr) { return 0x00; } -void BSXCartridge::mmio_write(unsigned addr, uint8 data) { +auto MCC::mmio_write(unsigned addr, uint8 data) -> void { if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000 uint8 n = (addr >> 16) & 15; r[n] = data; @@ -124,7 +124,7 @@ void BSXCartridge::mmio_write(unsigned addr, uint8 data) { } } -void BSXCartridge::mmio_commit() { +auto MCC::mmio_commit() -> void { r00 = r[0x00] & 0x80; r01 = r[0x01] & 0x80; r02 = r[0x02] & 0x80; diff --git a/sfc/chip/mcc/mcc.hpp b/sfc/chip/mcc/mcc.hpp new file mode 100644 index 00000000..dba2868f --- /dev/null +++ b/sfc/chip/mcc/mcc.hpp @@ -0,0 +1,36 @@ +//the MCC is the custom logic chip inside the BS-X Satellaview cartridge + +struct MCC { + MappedRAM rom; + MappedRAM ram; + MappedRAM psram; + + auto init() -> void; + auto load() -> void; + auto unload() -> void; + auto power() -> void; + auto reset() -> void; + + auto memory_access(bool write, Memory& memory, unsigned addr, uint8 data) -> uint8; + auto memory_read(Memory& memory, unsigned addr) -> uint8; + auto memory_write(Memory& memory, unsigned addr, uint8 data) -> void; + + auto mcu_access(bool write, unsigned addr, uint8 data = 0x00) -> uint8; + auto mcu_read(unsigned addr) -> uint8; + auto mcu_write(unsigned addr, uint8 data) -> void; + + auto mmio_read(unsigned addr) -> uint8; + auto mmio_write(unsigned addr, uint8 data) -> void; + auto mmio_commit() -> void; + + auto serialize(serializer&) -> void; + +private: + uint8 r[16]; + bool r00, r01, r02, r03; + bool r04, r05, r06, r07; + bool r08, r09, r0a, r0b; + bool r0c, r0d, r0e, r0f; +}; + +extern MCC mcc; diff --git a/sfc/chip/bsx/serialization.cpp b/sfc/chip/mcc/serialization.cpp similarity index 58% rename from sfc/chip/bsx/serialization.cpp rename to sfc/chip/mcc/serialization.cpp index e4ee4264..b845bce1 100644 --- a/sfc/chip/bsx/serialization.cpp +++ b/sfc/chip/mcc/serialization.cpp @@ -1,6 +1,6 @@ -#ifdef BSX_CPP +#ifdef MCC_CPP -void BSXCartridge::serialize(serializer& s) { +auto MCC::serialize(serializer& s) -> void { s.array(ram.data(), ram.size()); s.array(psram.data(), psram.size()); } diff --git a/sfc/chip/necdsp/serialization.cpp b/sfc/chip/necdsp/serialization.cpp index 36bbca5c..f9f61138 100644 --- a/sfc/chip/necdsp/serialization.cpp +++ b/sfc/chip/necdsp/serialization.cpp @@ -2,7 +2,7 @@ vector NECDSP::firmware() { vector buffer; - if(cartridge.has_necdsp() == false) return buffer; + if(!cartridge.hasNECDSP()) return buffer; unsigned plength = 2048, dlength = 1024; if(revision == Revision::uPD96050) plength = 16384, dlength = 2048; buffer.reserve(plength * 3 + dlength * 2); diff --git a/sfc/interface/interface.cpp b/sfc/interface/interface.cpp index 66b7c643..205a06cc 100644 --- a/sfc/interface/interface.cpp +++ b/sfc/interface/interface.cpp @@ -66,9 +66,9 @@ unsigned Interface::group(unsigned id) { case ID::SDD1RAM: case ID::OBC1RAM: case ID::SuperGameBoyBootROM: - case ID::BsxROM: - case ID::BsxRAM: - case ID::BsxPSRAM: + case ID::MCCROM: + case ID::MCCRAM: + case ID::MCCPSRAM: return 1; case ID::SuperGameBoy: case ID::SuperGameBoyManifest: @@ -96,10 +96,10 @@ unsigned Interface::group(unsigned id) { void Interface::load(unsigned id) { if(id == ID::SuperFamicom) cartridge.load(); - if(id == ID::SuperGameBoy) cartridge.load_super_game_boy(); - if(id == ID::Satellaview) cartridge.load_satellaview(); - if(id == ID::SufamiTurboSlotA) cartridge.load_sufami_turbo_a(); - if(id == ID::SufamiTurboSlotB) cartridge.load_sufami_turbo_b(); + if(id == ID::SuperGameBoy) cartridge.loadSuperGameBoy(); + if(id == ID::Satellaview) cartridge.loadSatellaview(); + if(id == ID::SufamiTurboSlotA) cartridge.loadSufamiTurboA(); + if(id == ID::SufamiTurboSlotB) cartridge.loadSufamiTurboB(); } void Interface::save() { @@ -193,9 +193,9 @@ void Interface::load(unsigned id, const stream& stream) { stream.read(GameBoy::system.bootROM.sgb, min(stream.size(), 256u)); } - if(id == ID::BsxROM) bsxcartridge.rom.read(stream); - if(id == ID::BsxRAM) bsxcartridge.ram.read(stream); - if(id == ID::BsxPSRAM) bsxcartridge.psram.read(stream); + if(id == ID::MCCROM) mcc.rom.read(stream); + if(id == ID::MCCRAM) mcc.ram.read(stream); + if(id == ID::MCCPSRAM) mcc.psram.read(stream); if(id == ID::SuperGameBoyManifest) cartridge.information.markup.gameBoy = stream.text(); @@ -260,8 +260,8 @@ void Interface::save(unsigned id, const stream& stream) { if(id == ID::SuperGameBoyRAM) stream.write(GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize); - if(id == ID::BsxRAM) stream.write(bsxcartridge.ram.data(), bsxcartridge.ram.size()); - if(id == ID::BsxPSRAM) stream.write(bsxcartridge.psram.data(), bsxcartridge.psram.size()); + if(id == ID::MCCRAM) stream.write(mcc.ram.data(), mcc.ram.size()); + if(id == ID::MCCPSRAM) stream.write(mcc.psram.data(), mcc.psram.size()); if(id == ID::SufamiTurboSlotARAM) stream.write(sufamiturboA.ram.data(), sufamiturboA.ram.size()); if(id == ID::SufamiTurboSlotBRAM) stream.write(sufamiturboB.ram.data(), sufamiturboB.ram.size()); @@ -289,14 +289,14 @@ void Interface::run() { } bool Interface::rtc() { - if(cartridge.has_epsonrtc()) return true; - if(cartridge.has_sharprtc()) return true; + if(cartridge.hasEpsonRTC()) return true; + if(cartridge.hasSharpRTC()) return true; return false; } void Interface::rtcsync() { - if(cartridge.has_epsonrtc()) epsonrtc.sync(); - if(cartridge.has_sharprtc()) sharprtc.sync(); + if(cartridge.hasEpsonRTC()) epsonrtc.sync(); + if(cartridge.hasSharpRTC()) sharprtc.sync(); } serializer Interface::serialize() { @@ -312,7 +312,7 @@ void Interface::cheatSet(const lstring& list) { cheat.reset(); //Super Game Boy - if(cartridge.has_gb_slot()) { + if(cartridge.hasICD2()) { GameBoy::cheat.reset(); for(auto& codeset : list) { lstring codes = codeset.split("+"); diff --git a/sfc/interface/interface.hpp b/sfc/interface/interface.hpp index e4f0f6dc..b98d6092 100644 --- a/sfc/interface/interface.hpp +++ b/sfc/interface/interface.hpp @@ -63,9 +63,9 @@ struct ID { SuperGameBoyBootROM, - BsxROM, - BsxRAM, - BsxPSRAM, + MCCROM, + MCCRAM, + MCCPSRAM, SuperGameBoyManifest, SuperGameBoyROM, diff --git a/sfc/system/serialization.cpp b/sfc/system/serialization.cpp index fe11e04a..0447fbf3 100644 --- a/sfc/system/serialization.cpp +++ b/sfc/system/serialization.cpp @@ -57,21 +57,22 @@ void System::serialize_all(serializer& s) { ppu.serialize(s); dsp.serialize(s); - if(cartridge.has_gb_slot()) icd2.serialize(s); - if(cartridge.has_bs_cart()) bsxcartridge.serialize(s); - if(cartridge.has_event()) event.serialize(s); - if(cartridge.has_sa1()) sa1.serialize(s); - if(cartridge.has_superfx()) superfx.serialize(s); - if(cartridge.has_armdsp()) armdsp.serialize(s); - if(cartridge.has_hitachidsp()) hitachidsp.serialize(s); - if(cartridge.has_necdsp()) necdsp.serialize(s); - if(cartridge.has_epsonrtc()) epsonrtc.serialize(s); - if(cartridge.has_sharprtc()) sharprtc.serialize(s); - if(cartridge.has_spc7110()) spc7110.serialize(s); - if(cartridge.has_sdd1()) sdd1.serialize(s); - if(cartridge.has_obc1()) obc1.serialize(s); - if(cartridge.has_msu1()) msu1.serialize(s); - if(cartridge.has_st_slots()) sufamiturboA.serialize(s), sufamiturboB.serialize(s); + if(cartridge.hasICD2()) icd2.serialize(s); + if(cartridge.hasMCC()) mcc.serialize(s); + if(cartridge.hasEvent()) event.serialize(s); + if(cartridge.hasSA1()) sa1.serialize(s); + if(cartridge.hasSuperFX()) superfx.serialize(s); + if(cartridge.hasARMDSP()) armdsp.serialize(s); + if(cartridge.hasHitachiDSP()) hitachidsp.serialize(s); + if(cartridge.hasNECDSP()) necdsp.serialize(s); + if(cartridge.hasEpsonRTC()) epsonrtc.serialize(s); + if(cartridge.hasSharpRTC()) sharprtc.serialize(s); + if(cartridge.hasSPC7110()) spc7110.serialize(s); + if(cartridge.hasSDD1()) sdd1.serialize(s); + if(cartridge.hasOBC1()) obc1.serialize(s); + if(cartridge.hasMSU1()) msu1.serialize(s); + + if(cartridge.hasSufamiTurboSlots()) sufamiturboA.serialize(s), sufamiturboB.serialize(s); } //perform dry-run state save: diff --git a/sfc/system/system.cpp b/sfc/system/system.cpp index 5c060802..3502e656 100644 --- a/sfc/system/system.cpp +++ b/sfc/system/system.cpp @@ -66,7 +66,7 @@ void System::init() { satellaviewbaseunit.init(); icd2.init(); - bsxcartridge.init(); + mcc.init(); nss.init(); event.init(); sa1.init(); @@ -120,46 +120,48 @@ void System::load() { ppu.enable(); if(expansion() == ExpansionPortDevice::Satellaview) satellaviewbaseunit.load(); - if(cartridge.has_gb_slot()) icd2.load(); - if(cartridge.has_bs_cart()) bsxcartridge.load(); - if(cartridge.has_nss_dip()) nss.load(); - if(cartridge.has_event()) event.load(); - if(cartridge.has_sa1()) sa1.load(); - if(cartridge.has_superfx()) superfx.load(); - if(cartridge.has_armdsp()) armdsp.load(); - if(cartridge.has_hitachidsp()) hitachidsp.load(); - if(cartridge.has_necdsp()) necdsp.load(); - if(cartridge.has_epsonrtc()) epsonrtc.load(); - if(cartridge.has_sharprtc()) sharprtc.load(); - if(cartridge.has_spc7110()) spc7110.load(); - if(cartridge.has_sdd1()) sdd1.load(); - if(cartridge.has_obc1()) obc1.load(); - if(cartridge.has_msu1()) msu1.load(); - if(cartridge.has_bs_slot()) satellaviewcartridge.load(); - if(cartridge.has_st_slots()) sufamiturboA.load(), sufamiturboB.load(); + if(cartridge.hasICD2()) icd2.load(); + if(cartridge.hasMCC()) mcc.load(); + if(cartridge.hasNSSDIP()) nss.load(); + if(cartridge.hasEvent()) event.load(); + if(cartridge.hasSA1()) sa1.load(); + if(cartridge.hasSuperFX()) superfx.load(); + if(cartridge.hasARMDSP()) armdsp.load(); + if(cartridge.hasHitachiDSP()) hitachidsp.load(); + if(cartridge.hasNECDSP()) necdsp.load(); + if(cartridge.hasEpsonRTC()) epsonrtc.load(); + if(cartridge.hasSharpRTC()) sharprtc.load(); + if(cartridge.hasSPC7110()) spc7110.load(); + if(cartridge.hasSDD1()) sdd1.load(); + if(cartridge.hasOBC1()) obc1.load(); + if(cartridge.hasMSU1()) msu1.load(); + + if(cartridge.hasSatellaviewSlot()) satellaviewcartridge.load(); + if(cartridge.hasSufamiTurboSlots()) sufamiturboA.load(), sufamiturboB.load(); serialize_init(); } void System::unload() { if(expansion() == ExpansionPortDevice::Satellaview) satellaviewbaseunit.unload(); - if(cartridge.has_gb_slot()) icd2.unload(); - if(cartridge.has_bs_cart()) bsxcartridge.unload(); - if(cartridge.has_nss_dip()) nss.unload(); - if(cartridge.has_event()) event.unload(); - if(cartridge.has_sa1()) sa1.unload(); - if(cartridge.has_superfx()) superfx.unload(); - if(cartridge.has_armdsp()) armdsp.unload(); - if(cartridge.has_hitachidsp()) hitachidsp.unload(); - if(cartridge.has_necdsp()) necdsp.unload(); - if(cartridge.has_epsonrtc()) epsonrtc.unload(); - if(cartridge.has_sharprtc()) sharprtc.unload(); - if(cartridge.has_spc7110()) spc7110.unload(); - if(cartridge.has_sdd1()) sdd1.unload(); - if(cartridge.has_obc1()) obc1.unload(); - if(cartridge.has_msu1()) msu1.unload(); - if(cartridge.has_bs_slot()) satellaviewcartridge.unload(); - if(cartridge.has_st_slots()) sufamiturboA.unload(), sufamiturboB.unload(); + if(cartridge.hasICD2()) icd2.unload(); + if(cartridge.hasMCC()) mcc.unload(); + if(cartridge.hasNSSDIP()) nss.unload(); + if(cartridge.hasEvent()) event.unload(); + if(cartridge.hasSA1()) sa1.unload(); + if(cartridge.hasSuperFX()) superfx.unload(); + if(cartridge.hasARMDSP()) armdsp.unload(); + if(cartridge.hasHitachiDSP()) hitachidsp.unload(); + if(cartridge.hasNECDSP()) necdsp.unload(); + if(cartridge.hasEpsonRTC()) epsonrtc.unload(); + if(cartridge.hasSharpRTC()) sharprtc.unload(); + if(cartridge.hasSPC7110()) spc7110.unload(); + if(cartridge.hasSDD1()) sdd1.unload(); + if(cartridge.hasOBC1()) obc1.unload(); + if(cartridge.hasMSU1()) msu1.unload(); + + if(cartridge.hasSatellaviewSlot()) satellaviewcartridge.unload(); + if(cartridge.hasSufamiTurboSlots()) sufamiturboA.unload(), sufamiturboB.unload(); } void System::power() { @@ -171,22 +173,23 @@ void System::power() { ppu.power(); if(expansion() == ExpansionPortDevice::Satellaview) satellaviewbaseunit.power(); - if(cartridge.has_gb_slot()) icd2.power(); - if(cartridge.has_bs_cart()) bsxcartridge.power(); - if(cartridge.has_nss_dip()) nss.power(); - if(cartridge.has_event()) event.power(); - if(cartridge.has_sa1()) sa1.power(); - if(cartridge.has_superfx()) superfx.power(); - if(cartridge.has_armdsp()) armdsp.power(); - if(cartridge.has_hitachidsp()) hitachidsp.power(); - if(cartridge.has_necdsp()) necdsp.power(); - if(cartridge.has_epsonrtc()) epsonrtc.power(); - if(cartridge.has_sharprtc()) sharprtc.power(); - if(cartridge.has_spc7110()) spc7110.power(); - if(cartridge.has_sdd1()) sdd1.power(); - if(cartridge.has_obc1()) obc1.power(); - if(cartridge.has_msu1()) msu1.power(); - if(cartridge.has_bs_slot()) satellaviewcartridge.power(); + if(cartridge.hasICD2()) icd2.power(); + if(cartridge.hasMCC()) mcc.power(); + if(cartridge.hasNSSDIP()) nss.power(); + if(cartridge.hasEvent()) event.power(); + if(cartridge.hasSA1()) sa1.power(); + if(cartridge.hasSuperFX()) superfx.power(); + if(cartridge.hasARMDSP()) armdsp.power(); + if(cartridge.hasHitachiDSP()) hitachidsp.power(); + if(cartridge.hasNECDSP()) necdsp.power(); + if(cartridge.hasEpsonRTC()) epsonrtc.power(); + if(cartridge.hasSharpRTC()) sharprtc.power(); + if(cartridge.hasSPC7110()) spc7110.power(); + if(cartridge.hasSDD1()) sdd1.power(); + if(cartridge.hasOBC1()) obc1.power(); + if(cartridge.hasMSU1()) msu1.power(); + + if(cartridge.hasSatellaviewSlot()) satellaviewcartridge.power(); reset(); } @@ -198,34 +201,35 @@ void System::reset() { ppu.reset(); if(expansion() == ExpansionPortDevice::Satellaview) satellaviewbaseunit.reset(); - if(cartridge.has_gb_slot()) icd2.reset(); - if(cartridge.has_bs_cart()) bsxcartridge.reset(); - if(cartridge.has_nss_dip()) nss.reset(); - if(cartridge.has_event()) event.reset(); - if(cartridge.has_sa1()) sa1.reset(); - if(cartridge.has_superfx()) superfx.reset(); - if(cartridge.has_armdsp()) armdsp.reset(); - if(cartridge.has_hitachidsp()) hitachidsp.reset(); - if(cartridge.has_necdsp()) necdsp.reset(); - if(cartridge.has_epsonrtc()) epsonrtc.reset(); - if(cartridge.has_sharprtc()) sharprtc.reset(); - if(cartridge.has_spc7110()) spc7110.reset(); - if(cartridge.has_sdd1()) sdd1.reset(); - if(cartridge.has_obc1()) obc1.reset(); - if(cartridge.has_msu1()) msu1.reset(); - if(cartridge.has_bs_slot()) satellaviewcartridge.reset(); + if(cartridge.hasICD2()) icd2.reset(); + if(cartridge.hasMCC()) mcc.reset(); + if(cartridge.hasNSSDIP()) nss.reset(); + if(cartridge.hasEvent()) event.reset(); + if(cartridge.hasSA1()) sa1.reset(); + if(cartridge.hasSuperFX()) superfx.reset(); + if(cartridge.hasARMDSP()) armdsp.reset(); + if(cartridge.hasHitachiDSP()) hitachidsp.reset(); + if(cartridge.hasNECDSP()) necdsp.reset(); + if(cartridge.hasEpsonRTC()) epsonrtc.reset(); + if(cartridge.hasSharpRTC()) sharprtc.reset(); + if(cartridge.hasSPC7110()) spc7110.reset(); + if(cartridge.hasSDD1()) sdd1.reset(); + if(cartridge.hasOBC1()) obc1.reset(); + if(cartridge.hasMSU1()) msu1.reset(); - if(cartridge.has_gb_slot()) cpu.coprocessors.append(&icd2); - if(cartridge.has_event()) cpu.coprocessors.append(&event); - if(cartridge.has_sa1()) cpu.coprocessors.append(&sa1); - if(cartridge.has_superfx()) cpu.coprocessors.append(&superfx); - if(cartridge.has_armdsp()) cpu.coprocessors.append(&armdsp); - if(cartridge.has_hitachidsp()) cpu.coprocessors.append(&hitachidsp); - if(cartridge.has_necdsp()) cpu.coprocessors.append(&necdsp); - if(cartridge.has_epsonrtc()) cpu.coprocessors.append(&epsonrtc); - if(cartridge.has_sharprtc()) cpu.coprocessors.append(&sharprtc); - if(cartridge.has_spc7110()) cpu.coprocessors.append(&spc7110); - if(cartridge.has_msu1()) cpu.coprocessors.append(&msu1); + if(cartridge.hasSatellaviewSlot()) satellaviewcartridge.reset(); + + if(cartridge.hasICD2()) cpu.coprocessors.append(&icd2); + if(cartridge.hasEvent()) cpu.coprocessors.append(&event); + if(cartridge.hasSA1()) cpu.coprocessors.append(&sa1); + if(cartridge.hasSuperFX()) cpu.coprocessors.append(&superfx); + if(cartridge.hasARMDSP()) cpu.coprocessors.append(&armdsp); + if(cartridge.hasHitachiDSP()) cpu.coprocessors.append(&hitachidsp); + if(cartridge.hasNECDSP()) cpu.coprocessors.append(&necdsp); + if(cartridge.hasEpsonRTC()) cpu.coprocessors.append(&epsonrtc); + if(cartridge.hasSharpRTC()) cpu.coprocessors.append(&sharprtc); + if(cartridge.hasSPC7110()) cpu.coprocessors.append(&spc7110); + if(cartridge.hasMSU1()) cpu.coprocessors.append(&msu1); scheduler.init(); input.connect(0, configuration.controller_port1); diff --git a/target-tomoko/tomoko.cpp b/target-tomoko/tomoko.cpp index e033fde2..4996f423 100644 --- a/target-tomoko/tomoko.cpp +++ b/target-tomoko/tomoko.cpp @@ -7,8 +7,8 @@ Emulator::Interface* emulator = nullptr; //if file already exists in the same path as the binary; use it (portable mode) //if not, use default requested path (*nix/user mode) auto locate(string pathname, string filename) -> string { - string location = {programpath(), filename}; - if(storage::exists(location)) return location; + string location{programpath(), filename}; + if(file_system_object::exists(location)) return location; return {pathname, filename}; } diff --git a/target-tomoko/tools/state-manager.cpp b/target-tomoko/tools/state-manager.cpp index ebca1b81..aae0463f 100644 --- a/target-tomoko/tools/state-manager.cpp +++ b/target-tomoko/tools/state-manager.cpp @@ -48,7 +48,7 @@ auto StateManager::doChangeSelected() -> void { if(buffer.size() >= 584) { string description; description.reserve(512); - memory::copy(description.pointer(), buffer.data() + 72, 512); + memory::copy(description.get(), buffer.data() + 72, 512); description.resize(description.length()); descriptionValue.setEnabled(true).setText(description); return doUpdateControls(); @@ -65,7 +65,7 @@ auto StateManager::doRefresh() -> void { if(buffer.size() >= 584) { string description; description.reserve(512); - memory::copy(description.pointer(), buffer.data() + 72, 512); + memory::copy(description.get(), buffer.data() + 72, 512); description.resize(description.length()); stateList.item(slot).cell(1).setText(description).setForegroundColor({0, 0, 0}); } else {