Update to v095r11 release.

byuu says:

Changelog:
- SFC: "uint8 read(uint addr)" -> "uint8 read(uint addr, uint8 data)"
- hiro: mHorizontalLayout::setGeometry() return value
- hiro/GTK: ListView,TreeView::setFocused() does not grab focus of first
  item

Notes:
- nall/windows/utf8.hpp needs using uint = unsigned; at the top to
  compile
- sfc/balanced, sfc/performance won't compile yet

Seems Cx4 games broke a while back. Not from this WIP, either. I'll go
back and find out what's wrong now.
This commit is contained in:
Tim Allen 2015-12-14 20:41:06 +11:00
parent 78d49d3873
commit f2a416aea9
97 changed files with 1104 additions and 1030 deletions

View File

@ -7,7 +7,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "095.10";
static const string Version = "095.11";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "http://byuu.org/";

View File

@ -60,6 +60,7 @@
#if defined(Hiro_Object)
struct Object : sObject {
DeclareSharedObject(Object)
using internalType = mObject;
template<typename T> auto cast() -> T {
if(auto pointer = dynamic_cast<typename T::internalType*>(data())) {
@ -73,14 +74,23 @@ struct Object : sObject {
#if defined(Hiro_Group)
struct Group : sGroup {
DeclareShared(Group)
using internalType = mGroup;
template<typename... P> Group(P&&... p) : Group() { _append(std::forward<P>(p)...); }
auto append(sObject object) -> type& { return self().append(object), *this; }
auto object(unsigned position) const { return self().object(position); }
auto objectCount() const { return self().objectCount(); }
auto objects() const { return self().objects(); }
//auto objects() const { return self().objects(); }
auto remove(sObject object) -> type& { return self().remove(object), *this; }
template<typename T = Object> auto objects() const -> vector<T> {
vector<T> objects;
for(auto object : self().objects()) {
if(auto cast = object.cast<T>()) objects.append(cast);
}
return objects;
}
private:
auto _append() {}
template<typename T, typename... P> auto _append(T* object, P&&... p) {
@ -93,6 +103,7 @@ private:
#if defined(Hiro_Timer)
struct Timer : sTimer {
DeclareSharedObject(Timer)
using internalType = mTimer;
auto doActivate() const { return self().doActivate(); }
auto interval() const { return self().interval(); }
@ -104,12 +115,14 @@ struct Timer : sTimer {
#if defined(Hiro_Action)
struct Action : sAction {
DeclareSharedAction(Action)
using internalType = mAction;
};
#endif
#if defined(Hiro_Menu)
struct Menu : sMenu {
DeclareSharedAction(Menu)
using internalType = mMenu;
auto action(unsigned position) const { return self().action(position); }
auto actionCount() const { return self().actionCount(); }
@ -127,12 +140,14 @@ struct Menu : sMenu {
#if defined(Hiro_MenuSeparator)
struct MenuSeparator : sMenuSeparator {
DeclareSharedAction(MenuSeparator)
using internalType = mMenuSeparator;
};
#endif
#if defined(Hiro_MenuItem)
struct MenuItem : sMenuItem {
DeclareSharedAction(MenuItem)
using internalType = mMenuItem;
auto doActivate() const { return self().doActivate(); }
auto image() const { return self().image(); }
@ -146,6 +161,7 @@ struct MenuItem : sMenuItem {
#if defined(Hiro_MenuCheckItem)
struct MenuCheckItem : sMenuCheckItem {
DeclareSharedAction(MenuCheckItem)
using internalType = mMenuCheckItem;
auto checked() const { return self().checked(); }
auto doToggle() const { return self().doToggle(); }
@ -174,24 +190,28 @@ struct MenuRadioItem : sMenuRadioItem {
#if defined(Hiro_Sizable)
struct Sizable : sSizable {
DeclareSharedSizable(Sizable)
using internalType = mSizable;
};
#endif
#if defined(Hiro_Layout)
struct Layout : sLayout {
DeclareSharedLayout(Layout)
using internalType = mLayout;
};
#endif
#if defined(Hiro_Widget)
struct Widget : sWidget {
DeclareSharedWidget(Widget)
using internalType = mWidget;
};
#endif
#if defined(Hiro_Button)
struct Button : sButton {
DeclareSharedWidget(Button)
using internalType = mButton;
auto bordered() const { return self().bordered(); }
auto doActivate() const { return self().doActivate(); }
@ -209,6 +229,7 @@ struct Button : sButton {
#if defined(Hiro_Canvas)
struct Canvas : sCanvas {
DeclareSharedWidget(Canvas)
using internalType = mCanvas;
auto color() const { return self().color(); }
auto data() { return self().data(); }
@ -237,6 +258,7 @@ struct Canvas : sCanvas {
#if defined(Hiro_CheckButton)
struct CheckButton : sCheckButton {
DeclareSharedWidget(CheckButton)
using internalType = mCheckButton;
auto bordered() const { return self().bordered(); }
auto checked() const { return self().checked(); }
@ -256,6 +278,7 @@ struct CheckButton : sCheckButton {
#if defined(Hiro_CheckLabel)
struct CheckLabel : sCheckLabel {
DeclareSharedWidget(CheckLabel)
using internalType = mCheckLabel;
auto checked() const { return self().checked(); }
auto doToggle() const { return self().doToggle(); }
@ -269,6 +292,7 @@ struct CheckLabel : sCheckLabel {
#if defined(Hiro_ComboButton)
struct ComboButtonItem : sComboButtonItem {
DeclareSharedObject(ComboButtonItem)
using internalType = mComboButtonItem;
auto image() const { return self().image(); }
auto selected() const { return self().selected(); }
@ -282,6 +306,7 @@ struct ComboButtonItem : sComboButtonItem {
#if defined(Hiro_ComboButton)
struct ComboButton : sComboButton {
DeclareSharedWidget(ComboButton)
using internalType = mComboButton;
auto append(sComboButtonItem item) { return self().append(item), *this; }
auto doChange() const { return self().doChange(); }
@ -299,6 +324,7 @@ struct ComboButton : sComboButton {
#if defined(Hiro_Console)
struct Console : sConsole {
DeclareSharedWidget(Console)
using internalType = mConsole;
auto backgroundColor() const { return self().backgroundColor(); }
auto doActivate(string command) const { return self().doActivate(command); }
@ -316,6 +342,7 @@ struct Console : sConsole {
#if defined(Hiro_Frame)
struct Frame : sFrame {
DeclareSharedWidget(Frame)
using internalType = mFrame;
auto append(sLayout layout) { return self().append(layout), *this; }
auto layout() const { return self().layout(); }
@ -329,6 +356,7 @@ struct Frame : sFrame {
#if defined(Hiro_HexEdit)
struct HexEdit : sHexEdit {
DeclareSharedWidget(HexEdit)
using internalType = mHexEdit;
auto address() const { return self().address(); }
auto backgroundColor() const { return self().backgroundColor(); }
@ -353,6 +381,7 @@ struct HexEdit : sHexEdit {
#if defined(Hiro_HorizontalScrollBar)
struct HorizontalScrollBar : sHorizontalScrollBar {
DeclareSharedWidget(HorizontalScrollBar)
using internalType = mHorizontalScrollBar;
auto doChange() const { return self().doChange(); }
auto length() const { return self().length(); }
@ -366,6 +395,7 @@ struct HorizontalScrollBar : sHorizontalScrollBar {
#if defined(Hiro_HorizontalSlider)
struct HorizontalSlider : sHorizontalSlider {
DeclareSharedWidget(HorizontalSlider)
using internalType = mHorizontalSlider;
auto doChange() const { return self().doChange(); }
auto length() const { return self().length(); }
@ -379,6 +409,7 @@ struct HorizontalSlider : sHorizontalSlider {
#if defined(Hiro_IconView)
struct IconViewItem : sIconViewItem {
DeclareSharedObject(IconViewItem)
using internalType = mIconViewItem;
auto image() const { return self().image(); }
auto selected() const { return self().selected(); }
@ -392,6 +423,7 @@ struct IconViewItem : sIconViewItem {
#if defined(Hiro_IconView)
struct IconView : sIconView {
DeclareSharedWidget(IconView)
using internalType = mIconView;
auto append(sIconViewItem item) { return self().append(item), *this; }
auto backgroundColor() const { return self().backgroundColor(); }
@ -424,6 +456,7 @@ struct IconView : sIconView {
#if defined(Hiro_Label)
struct Label : sLabel {
DeclareSharedWidget(Label)
using internalType = mLabel;
auto alignment() const { return self().alignment(); }
auto setAlignment(Alignment alignment = {}) { return self().setAlignment(alignment), *this; }
@ -435,6 +468,7 @@ struct Label : sLabel {
#if defined(Hiro_LineEdit)
struct LineEdit : sLineEdit {
DeclareSharedWidget(LineEdit)
using internalType = mLineEdit;
auto backgroundColor() const { return self().backgroundColor(); }
auto doActivate() const { return self().doActivate(); }
@ -454,6 +488,7 @@ struct LineEdit : sLineEdit {
#if defined(Hiro_ListView)
struct ListViewColumn : sListViewColumn {
DeclareSharedObject(ListViewColumn)
using internalType = mListViewColumn;
auto active() const { return self().active(); }
auto alignment() const { return self().alignment(); }
@ -485,6 +520,7 @@ struct ListViewColumn : sListViewColumn {
#if defined(Hiro_ListView)
struct ListViewHeader : sListViewHeader {
DeclareSharedObject(ListViewHeader)
using internalType = mListViewHeader;
auto append(sListViewColumn column) { return self().append(column), *this; }
auto column(unsigned position) const { return self().column(position); }
@ -497,6 +533,7 @@ struct ListViewHeader : sListViewHeader {
#if defined(Hiro_ListView)
struct ListViewCell : sListViewCell {
DeclareSharedObject(ListViewCell)
using internalType = mListViewCell;
auto alignment() const { return self().alignment(); }
auto backgroundColor() const { return self().backgroundColor(); }
@ -518,6 +555,7 @@ struct ListViewCell : sListViewCell {
#if defined(Hiro_ListView)
struct ListViewItem : sListViewItem {
DeclareSharedObject(ListViewItem)
using internalType = mListViewItem;
auto alignment() const { return self().alignment(); }
auto append(sListViewCell cell) { return self().append(cell), *this; }
@ -538,6 +576,7 @@ struct ListViewItem : sListViewItem {
#if defined(Hiro_ListView)
struct ListView : sListView {
DeclareSharedWidget(ListView)
using internalType = mListView;
auto alignment() const { return self().alignment(); }
auto append(sListViewHeader header) { return self().append(header), *this; }
@ -579,6 +618,7 @@ struct ListView : sListView {
#if defined(Hiro_ProgressBar)
struct ProgressBar : sProgressBar {
DeclareSharedWidget(ProgressBar)
using internalType = mProgressBar;
auto position() const { return self().position(); }
auto setPosition(unsigned position = 0) { return self().setPosition(position), *this; }
@ -624,6 +664,7 @@ struct RadioLabel : sRadioLabel {
#if defined(Hiro_SourceEdit)
struct SourceEdit : sSourceEdit {
DeclareSharedWidget(SourceEdit)
using internalType = mSourceEdit;
auto cursor() const { return self().cursor(); }
auto doChange() const { return self().doChange(); }
@ -639,6 +680,7 @@ struct SourceEdit : sSourceEdit {
#if defined(Hiro_TabFrame)
struct TabFrameItem : sTabFrameItem {
DeclareSharedObject(TabFrameItem)
using internalType = mTabFrameItem;
auto append(sLayout layout) { return self().append(layout), *this; }
auto closable() const { return self().closable(); }
@ -660,6 +702,7 @@ struct TabFrameItem : sTabFrameItem {
#if defined(Hiro_TabFrame)
struct TabFrame : sTabFrame {
DeclareSharedWidget(TabFrame)
using internalType = mTabFrame;
auto append(sTabFrameItem item) { return self().append(item), *this; }
auto doChange() const { return self().doChange(); }
@ -682,6 +725,7 @@ struct TabFrame : sTabFrame {
#if defined(Hiro_TextEdit)
struct TextEdit : sTextEdit {
DeclareSharedWidget(TextEdit)
using internalType = mTextEdit;
auto backgroundColor() const { return self().backgroundColor(); }
auto cursor() const { return self().cursor(); }
@ -705,6 +749,7 @@ struct TextEdit : sTextEdit {
#if defined(Hiro_TreeView)
struct TreeViewItem : sTreeViewItem {
DeclareSharedObject(TreeViewItem)
using internalType = mTreeViewItem;
auto append(sTreeViewItem item) { return self().append(item), *this; }
auto backgroundColor() const { return self().backgroundColor(); }
@ -733,6 +778,7 @@ struct TreeViewItem : sTreeViewItem {
#if defined(Hiro_TreeView)
struct TreeView : sTreeView {
DeclareSharedWidget(TreeView)
using internalType = mTreeView;
auto append(sTreeViewItem item) { return self().append(item), *this; }
auto backgroundColor() const { return self().backgroundColor(); }
@ -759,6 +805,7 @@ struct TreeView : sTreeView {
#if defined(Hiro_VerticalScrollBar)
struct VerticalScrollBar : sVerticalScrollBar {
DeclareSharedWidget(VerticalScrollBar)
using internalType = mVerticalScrollBar;
auto doChange() const { return self().doChange(); }
auto length() const { return self().length(); }
@ -772,6 +819,7 @@ struct VerticalScrollBar : sVerticalScrollBar {
#if defined(Hiro_VerticalSlider)
struct VerticalSlider : sVerticalSlider {
DeclareSharedWidget(VerticalSlider)
using internalType = mVerticalSlider;
auto doChange() const { return self().doChange(); }
auto length() const { return self().length(); }
@ -785,6 +833,7 @@ struct VerticalSlider : sVerticalSlider {
#if defined(Hiro_Viewport)
struct Viewport : sViewport {
DeclareSharedWidget(Viewport)
using internalType = mViewport;
auto doDrop(lstring names) const { return self().doDrop(names); }
auto doMouseLeave() const { return self().doMouseLeave(); }
@ -805,6 +854,7 @@ struct Viewport : sViewport {
#if defined(Hiro_StatusBar)
struct StatusBar : sStatusBar {
DeclareSharedObject(StatusBar)
using internalType = mStatusBar;
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
@ -814,6 +864,7 @@ struct StatusBar : sStatusBar {
#if defined(Hiro_PopupMenu)
struct PopupMenu : sPopupMenu {
DeclareSharedObject(PopupMenu)
using internalType = mPopupMenu;
auto action(unsigned position) const { return self().action(position); }
auto actionCount() const { return self().actionCount(); }
@ -827,6 +878,7 @@ struct PopupMenu : sPopupMenu {
#if defined(Hiro_MenuBar)
struct MenuBar : sMenuBar {
DeclareSharedObject(MenuBar)
using internalType = mMenuBar;
auto append(sMenu menu) { return self().append(menu), *this; }
auto menu(unsigned position) const { return self().menu(position); }
@ -840,6 +892,7 @@ struct MenuBar : sMenuBar {
#if defined(Hiro_Window)
struct Window : sWindow {
DeclareSharedObject(Window)
using internalType = mWindow;
auto append(sLayout layout) { return self().append(layout), *this; }
auto append(sMenuBar menuBar) { return self().append(menuBar), *this; }

View File

@ -189,7 +189,6 @@ auto BrowserDialogWindow::setPath(string path) -> void {
);
}
if(view.items()) view.item(0)->setSelected();
Application::processEvents();
view.resizeColumns().setFocused().doChange();
}

View File

@ -116,6 +116,8 @@ auto mHorizontalLayout::setGeometry(Geometry containerGeometry) -> type& {
geometry.setX (geometry.x() + child.width + child.spacing);
geometry.setWidth(geometry.width() - child.width + child.spacing);
}
return *this;
}
auto mHorizontalLayout::setMargin(signed margin) -> type& {

View File

@ -119,7 +119,13 @@ auto pListView::setBordered(bool bordered) -> void {
}
auto pListView::setFocused() -> void {
//gtk_widget_grab_focus() will select the first item if nothing is currently selected
//this behavior is undesirable. detect selection state first, and restore if required
lock();
bool selected = gtk_tree_selection_get_selected(gtkTreeSelection, nullptr, nullptr);
gtk_widget_grab_focus(gtkWidgetChild);
if(!selected) gtk_tree_selection_unselect_all(gtkTreeSelection);
unlock();
}
auto pListView::setFont(const Font& font) -> void {

View File

@ -79,6 +79,16 @@ auto pTreeView::setBackgroundColor(Color color) -> void {
gtk_widget_modify_base(gtkWidgetChild, GTK_STATE_NORMAL, color ? &gdkColor : nullptr);
}
auto pTreeView::setFocused() -> void {
//gtk_widget_grab_focus() will select the first item if nothing is currently selected
//this behavior is undesirable. detect selection state first, and restore if required
lock();
bool selected = gtk_tree_selection_get_selected(gtkTreeSelection, nullptr, nullptr);
gtk_widget_grab_focus(gtkWidgetChild);
if(!selected) gtk_tree_selection_unselect_all(gtkTreeSelection);
unlock();
}
auto pTreeView::setForegroundColor(Color color) -> void {
auto gdkColor = CreateColor(color);
gtk_widget_modify_text(gtkWidgetChild, GTK_STATE_NORMAL, color ? &gdkColor : nullptr);

View File

@ -8,6 +8,7 @@ struct pTreeView : pWidget {
auto append(sTreeViewItem item) -> void;
auto remove(sTreeViewItem item) -> void;
auto setBackgroundColor(Color color) -> void;
auto setFocused() -> void override;
auto setForegroundColor(Color color) -> void;
auto _activatePath(GtkTreePath* gtkPath) -> void;

View File

@ -9,70 +9,70 @@
namespace nall {
struct bpsdelta {
inline void source(const uint8_t* data, unsigned size);
inline void target(const uint8_t* data, unsigned size);
inline auto source(const uint8* data, uint size) -> void;
inline auto target(const uint8* data, uint size) -> void;
inline bool source(const string& filename);
inline bool target(const string& filename);
inline bool create(const string& filename, const string& metadata = "");
inline auto source(const string& filename) -> bool;
inline auto target(const string& filename) -> bool;
inline auto create(const string& filename, const string& metadata = "") -> bool;
protected:
enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
enum : unsigned { Granularity = 1 };
enum : uint { SourceRead, TargetRead, SourceCopy, TargetCopy };
enum : uint { Granularity = 1 };
struct Node {
unsigned offset = 0;
Node* next = nullptr;
Node() = default;
~Node() { if(next) delete next; }
uint offset = 0;
Node* next = nullptr;
};
filemap sourceFile;
const uint8_t* sourceData;
unsigned sourceSize;
const uint8* sourceData;
uint sourceSize;
filemap targetFile;
const uint8_t* targetData;
unsigned targetSize;
const uint8* targetData;
uint targetSize;
};
void bpsdelta::source(const uint8_t* data, unsigned size) {
auto bpsdelta::source(const uint8* data, uint size) -> void {
sourceData = data;
sourceSize = size;
}
void bpsdelta::target(const uint8_t* data, unsigned size) {
auto bpsdelta::target(const uint8* data, uint size) -> void {
targetData = data;
targetSize = size;
}
bool bpsdelta::source(const string& filename) {
auto bpsdelta::source(const string& filename) -> bool {
if(sourceFile.open(filename, filemap::mode::read) == false) return false;
source(sourceFile.data(), sourceFile.size());
return true;
}
bool bpsdelta::target(const string& filename) {
auto bpsdelta::target(const string& filename) -> bool {
if(targetFile.open(filename, filemap::mode::read) == false) return false;
target(targetFile.data(), targetFile.size());
return true;
}
bool bpsdelta::create(const string& filename, const string& metadata) {
auto bpsdelta::create(const string& filename, const string& metadata) -> bool {
file modifyFile;
if(modifyFile.open(filename, file::mode::write) == false) return false;
Hash::CRC32 sourceChecksum, modifyChecksum;
unsigned sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0;
uint sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0;
auto write = [&](uint8_t data) {
auto write = [&](uint8 data) {
modifyFile.write(data);
modifyChecksum.data(data);
};
auto encode = [&](uint64_t data) {
auto encode = [&](uint64 data) {
while(true) {
uint64_t x = data & 0x7f;
uint64 x = data & 0x7f;
data >>= 7;
if(data == 0) {
write(0x80 | x);
@ -91,17 +91,17 @@ bool bpsdelta::create(const string& filename, const string& metadata) {
encode(sourceSize);
encode(targetSize);
unsigned markupSize = metadata.length();
uint markupSize = metadata.length();
encode(markupSize);
for(unsigned n = 0; n < markupSize; n++) write(metadata[n]);
for(uint n = 0; n < markupSize; n++) write(metadata[n]);
Node* sourceTree[65536];
Node* targetTree[65536];
for(unsigned n = 0; n < 65536; n++) sourceTree[n] = nullptr, targetTree[n] = nullptr;
for(uint n = 0; n < 65536; n++) sourceTree[n] = nullptr, targetTree[n] = nullptr;
//source tree creation
for(unsigned offset = 0; offset < sourceSize; offset++) {
uint16_t symbol = sourceData[offset + 0];
for(uint offset = 0; offset < sourceSize; offset++) {
uint16 symbol = sourceData[offset + 0];
sourceChecksum.data(symbol);
if(offset < sourceSize - 1) symbol |= sourceData[offset + 1] << 8;
Node *node = new Node;
@ -110,24 +110,24 @@ bool bpsdelta::create(const string& filename, const string& metadata) {
sourceTree[symbol] = node;
}
unsigned targetReadLength = 0;
uint targetReadLength = 0;
auto targetReadFlush = [&]() {
if(targetReadLength) {
encode(TargetRead | ((targetReadLength - 1) << 2));
unsigned offset = outputOffset - targetReadLength;
uint offset = outputOffset - targetReadLength;
while(targetReadLength) write(targetData[offset++]), targetReadLength--;
}
};
while(outputOffset < targetSize) {
unsigned maxLength = 0, maxOffset = 0, mode = TargetRead;
uint maxLength = 0, maxOffset = 0, mode = TargetRead;
uint16_t symbol = targetData[outputOffset + 0];
uint16 symbol = targetData[outputOffset + 0];
if(outputOffset < targetSize - 1) symbol |= targetData[outputOffset + 1] << 8;
{ //source read
unsigned length = 0, offset = outputOffset;
uint length = 0, offset = outputOffset;
while(offset < sourceSize && offset < targetSize && sourceData[offset] == targetData[offset]) {
length++;
offset++;
@ -138,7 +138,7 @@ bool bpsdelta::create(const string& filename, const string& metadata) {
{ //source copy
Node* node = sourceTree[symbol];
while(node) {
unsigned length = 0, x = node->offset, y = outputOffset;
uint length = 0, x = node->offset, y = outputOffset;
while(x < sourceSize && y < targetSize && sourceData[x++] == targetData[y++]) length++;
if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = SourceCopy;
node = node->next;
@ -148,7 +148,7 @@ bool bpsdelta::create(const string& filename, const string& metadata) {
{ //target copy
Node* node = targetTree[symbol];
while(node) {
unsigned length = 0, x = node->offset, y = outputOffset;
uint length = 0, x = node->offset, y = outputOffset;
while(y < targetSize && targetData[x++] == targetData[y++]) length++;
if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = TargetCopy;
node = node->next;
@ -163,7 +163,7 @@ bool bpsdelta::create(const string& filename, const string& metadata) {
{ //target read
if(maxLength < 4) {
maxLength = min((unsigned)Granularity, targetSize - outputOffset);
maxLength = min((uint)Granularity, targetSize - outputOffset);
mode = TargetRead;
}
}
@ -181,7 +181,7 @@ bool bpsdelta::create(const string& filename, const string& metadata) {
case SourceCopy:
case TargetCopy:
encode(mode | ((maxLength - 1) << 2));
signed relativeOffset;
int relativeOffset;
if(mode == SourceCopy) {
relativeOffset = maxOffset - sourceRelativeOffset;
sourceRelativeOffset = maxOffset + maxLength;
@ -198,11 +198,11 @@ bool bpsdelta::create(const string& filename, const string& metadata) {
targetReadFlush();
for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum.value() >> n);
uint32_t targetChecksum = Hash::CRC32(targetData, targetSize).value();
for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n);
uint32_t outputChecksum = modifyChecksum.value();
for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n);
for(uint n = 0; n < 32; n += 8) write(sourceChecksum.value() >> n);
uint32 targetChecksum = Hash::CRC32(targetData, targetSize).value();
for(uint n = 0; n < 32; n += 8) write(targetChecksum >> n);
uint32 outputChecksum = modifyChecksum.value();
for(uint n = 0; n < 32; n += 8) write(outputChecksum >> n);
modifyFile.close();
return true;

View File

@ -9,63 +9,63 @@
namespace nall {
struct bpslinear {
inline void source(const uint8_t* data, unsigned size);
inline void target(const uint8_t* data, unsigned size);
inline auto source(const uint8* data, uint size) -> void;
inline auto target(const uint8* data, uint size) -> void;
inline bool source(const string& filename);
inline bool target(const string& filename);
inline bool create(const string& filename, const string& metadata = "");
inline auto source(const string& filename) -> bool;
inline auto target(const string& filename) -> bool;
inline auto create(const string& filename, const string& metadata = "") -> bool;
protected:
enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
enum : unsigned { Granularity = 1 };
enum : uint { SourceRead, TargetRead, SourceCopy, TargetCopy };
enum : uint { Granularity = 1 };
filemap sourceFile;
const uint8_t* sourceData;
unsigned sourceSize;
const uint8* sourceData;
uint sourceSize;
filemap targetFile;
const uint8_t* targetData;
unsigned targetSize;
const uint8* targetData;
uint targetSize;
};
void bpslinear::source(const uint8_t* data, unsigned size) {
auto bpslinear::source(const uint8* data, uint size) -> void {
sourceData = data;
sourceSize = size;
}
void bpslinear::target(const uint8_t* data, unsigned size) {
auto bpslinear::target(const uint8* data, uint size) -> void {
targetData = data;
targetSize = size;
}
bool bpslinear::source(const string& filename) {
auto bpslinear::source(const string& filename) -> bool {
if(sourceFile.open(filename, filemap::mode::read) == false) return false;
source(sourceFile.data(), sourceFile.size());
return true;
}
bool bpslinear::target(const string& filename) {
auto bpslinear::target(const string& filename) -> bool {
if(targetFile.open(filename, filemap::mode::read) == false) return false;
target(targetFile.data(), targetFile.size());
return true;
}
bool bpslinear::create(const string& filename, const string& metadata) {
auto bpslinear::create(const string& filename, const string& metadata) -> bool {
file modifyFile;
if(modifyFile.open(filename, file::mode::write) == false) return false;
Hash::CRC32 modifyChecksum;
unsigned targetRelativeOffset = 0, outputOffset = 0;
uint targetRelativeOffset = 0, outputOffset = 0;
auto write = [&](uint8_t data) {
auto write = [&](uint8 data) {
modifyFile.write(data);
modifyChecksum.data(data);
};
auto encode = [&](uint64_t data) {
auto encode = [&](uint64 data) {
while(true) {
uint64_t x = data & 0x7f;
uint64 x = data & 0x7f;
data >>= 7;
if(data == 0) {
write(0x80 | x);
@ -76,12 +76,12 @@ bool bpslinear::create(const string& filename, const string& metadata) {
}
};
unsigned targetReadLength = 0;
uint targetReadLength = 0;
auto targetReadFlush = [&]() {
if(targetReadLength) {
encode(TargetRead | ((targetReadLength - 1) << 2));
unsigned offset = outputOffset - targetReadLength;
uint offset = outputOffset - targetReadLength;
while(targetReadLength) write(targetData[offset++]), targetReadLength--;
}
};
@ -94,19 +94,19 @@ bool bpslinear::create(const string& filename, const string& metadata) {
encode(sourceSize);
encode(targetSize);
unsigned markupSize = metadata.length();
uint markupSize = metadata.length();
encode(markupSize);
for(unsigned n = 0; n < markupSize; n++) write(metadata[n]);
for(uint n = 0; n < markupSize; n++) write(metadata[n]);
while(outputOffset < targetSize) {
unsigned sourceLength = 0;
for(unsigned n = 0; outputOffset + n < min(sourceSize, targetSize); n++) {
uint sourceLength = 0;
for(uint n = 0; outputOffset + n < min(sourceSize, targetSize); n++) {
if(sourceData[outputOffset + n] != targetData[outputOffset + n]) break;
sourceLength++;
}
unsigned rleLength = 0;
for(unsigned n = 1; outputOffset + n < targetSize; n++) {
uint rleLength = 0;
for(uint n = 1; outputOffset + n < targetSize; n++) {
if(targetData[outputOffset] != targetData[outputOffset + n]) break;
rleLength++;
}
@ -119,7 +119,7 @@ bool bpslinear::create(const string& filename, const string& metadata) {
//copy starting from repetition byte
encode(TargetCopy | ((rleLength - 1) << 2));
unsigned relativeOffset = (outputOffset - 1) - targetRelativeOffset;
uint relativeOffset = (outputOffset - 1) - targetRelativeOffset;
encode(relativeOffset << 1);
outputOffset += rleLength;
targetRelativeOffset = outputOffset - 1;
@ -135,12 +135,12 @@ bool bpslinear::create(const string& filename, const string& metadata) {
targetReadFlush();
uint32_t sourceChecksum = Hash::CRC32(sourceData, sourceSize).value();
for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n);
uint32_t targetChecksum = Hash::CRC32(targetData, targetSize).value();
for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n);
uint32_t outputChecksum = modifyChecksum.value();
for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n);
uint32 sourceChecksum = Hash::CRC32(sourceData, sourceSize).value();
for(uint n = 0; n < 32; n += 8) write(sourceChecksum >> n);
uint32 targetChecksum = Hash::CRC32(targetData, targetSize).value();
for(uint n = 0; n < 32; n += 8) write(targetChecksum >> n);
uint32 outputChecksum = modifyChecksum.value();
for(uint n = 0; n < 32; n += 8) write(outputChecksum >> n);
modifyFile.close();
return true;

View File

@ -9,26 +9,26 @@
namespace nall {
struct bpsmetadata {
inline bool load(const string& filename);
inline bool save(const string& filename, const string& metadata);
inline string metadata() const;
inline auto load(const string& filename) -> bool;
inline auto save(const string& filename, const string& metadata) -> bool;
inline auto metadata() const -> string;
protected:
file sourceFile;
string metadataString;
};
bool bpsmetadata::load(const string& filename) {
auto bpsmetadata::load(const string& filename) -> bool {
if(sourceFile.open(filename, file::mode::read) == false) return false;
auto read = [&]() -> uint8_t {
return sourceFile.read();
};
auto decode = [&]() -> uint64_t {
uint64_t data = 0, shift = 1;
auto decode = [&]() -> uint64 {
uint64 data = 0, shift = 1;
while(true) {
uint8_t x = read();
uint8 x = read();
data += (x & 0x7f) * shift;
if(x & 0x80) break;
shift <<= 7;
@ -43,29 +43,29 @@ bool bpsmetadata::load(const string& filename) {
if(read() != '1') return false;
decode();
decode();
unsigned metadataSize = decode();
uint metadataSize = decode();
char data[metadataSize + 1];
for(unsigned n = 0; n < metadataSize; n++) data[n] = read();
for(uint n = 0; n < metadataSize; n++) data[n] = read();
data[metadataSize] = 0;
metadataString = (const char*)data;
return true;
}
bool bpsmetadata::save(const string& filename, const string& metadata) {
auto bpsmetadata::save(const string& filename, const string& metadata) -> bool {
file targetFile;
if(targetFile.open(filename, file::mode::write) == false) return false;
if(sourceFile.open() == false) return false;
sourceFile.seek(0);
auto read = [&]() -> uint8_t {
auto read = [&]() -> uint8 {
return sourceFile.read();
};
auto decode = [&]() -> uint64_t {
uint64_t data = 0, shift = 1;
auto decode = [&]() -> uint64 {
uint64 data = 0, shift = 1;
while(true) {
uint8_t x = read();
uint8 x = read();
data += (x & 0x7f) * shift;
if(x & 0x80) break;
shift <<= 7;
@ -76,14 +76,14 @@ bool bpsmetadata::save(const string& filename, const string& metadata) {
Hash::CRC32 checksum;
auto write = [&](uint8_t data) {
auto write = [&](uint8 data) {
targetFile.write(data);
checksum.data(data);
};
auto encode = [&](uint64_t data) {
auto encode = [&](uint64 data) {
while(true) {
uint64_t x = data & 0x7f;
uint64 x = data & 0x7f;
data >>= 7;
if(data == 0) {
write(0x80 | x);
@ -94,24 +94,24 @@ bool bpsmetadata::save(const string& filename, const string& metadata) {
}
};
for(unsigned n = 0; n < 4; n++) write(read());
for(uint n = 0; n < 4; n++) write(read());
encode(decode());
encode(decode());
unsigned sourceLength = decode();
unsigned targetLength = metadata.length();
uint sourceLength = decode();
uint targetLength = metadata.length();
encode(targetLength);
sourceFile.seek(sourceLength, file::index::relative);
for(unsigned n = 0; n < targetLength; n++) write(metadata[n]);
unsigned length = sourceFile.size() - sourceFile.offset() - 4;
for(unsigned n = 0; n < length; n++) write(read());
uint32_t outputChecksum = checksum.value();
for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n);
for(uint n = 0; n < targetLength; n++) write(metadata[n]);
uint length = sourceFile.size() - sourceFile.offset() - 4;
for(uint n = 0; n < length; n++) write(read());
uint32 outputChecksum = checksum.value();
for(uint n = 0; n < 32; n += 8) write(outputChecksum >> n);
targetFile.close();
return true;
}
string bpsmetadata::metadata() const {
auto bpsmetadata::metadata() const -> string {
return metadataString;
}

View File

@ -8,19 +8,19 @@
namespace nall {
struct bpsmulti {
enum : unsigned {
enum : uint {
CreatePath = 0,
CreateFile = 1,
ModifyFile = 2,
MirrorFile = 3,
};
enum : unsigned {
enum : uint {
OriginSource = 0,
OriginTarget = 1,
};
bool create(const string& patchName, const string& sourcePath, const string& targetPath, bool delta = false, const string& metadata = "") {
auto create(const string& patchName, const string& sourcePath, const string& targetPath, bool delta = false, const string& metadata = "") -> bool {
if(fp.open()) fp.close();
fp.open(patchName, file::mode::write);
checksum.reset();
@ -46,8 +46,8 @@ struct bpsmulti {
bool identical = sp.size() == dp.size();
Hash::CRC32 cksum;
for(unsigned n = 0; n < sp.size(); n++) {
uint8_t byte = sp.read();
for(uint n = 0; n < sp.size(); n++) {
uint8 byte = sp.read();
if(identical && byte != dp.read()) identical = false;
cksum.data(byte);
}
@ -83,7 +83,7 @@ struct bpsmulti {
writeString(targetName);
auto buffer = file::read({targetPath, targetName});
writeNumber(buffer.size());
for(auto &byte : buffer) write(byte);
for(auto& byte : buffer) write(byte);
writeChecksum(Hash::CRC32(buffer.data(), buffer.size()).value());
}
}
@ -94,7 +94,7 @@ struct bpsmulti {
return true;
}
bool apply(const string& patchName, const string& sourcePath, const string& targetPath) {
auto apply(const string& patchName, const string& sourcePath, const string& targetPath) -> bool {
directory::remove(targetPath); //start with a clean directory
directory::create(targetPath);
@ -108,8 +108,8 @@ struct bpsmulti {
while(fp.offset() < fp.size() - 4) {
auto encoding = readNumber();
unsigned action = encoding & 3;
unsigned targetLength = (encoding >> 2) + 1;
uint action = encoding & 3;
uint targetLength = (encoding >> 2) + 1;
string targetName = readString(targetLength);
if(action == CreatePath) {
@ -119,15 +119,15 @@ struct bpsmulti {
fp.open({targetPath, targetName}, file::mode::write);
auto fileSize = readNumber();
while(fileSize--) fp.write(read());
uint32_t cksum = readChecksum();
uint32 cksum = readChecksum();
} else if(action == ModifyFile) {
auto encoding = readNumber();
string originPath = encoding & 1 ? targetPath : sourcePath;
string sourceName = (encoding >> 1) == 0 ? targetName : readString(encoding >> 1);
auto patchSize = readNumber();
vector<uint8_t> buffer;
vector<uint8> buffer;
buffer.resize(patchSize);
for(unsigned n = 0; n < patchSize; n++) buffer[n] = read();
for(uint n = 0; n < patchSize; n++) buffer[n] = read();
bpspatch patch;
patch.modify(buffer.data(), buffer.size());
patch.source({originPath, sourceName});
@ -138,15 +138,15 @@ struct bpsmulti {
string originPath = encoding & 1 ? targetPath : sourcePath;
string sourceName = (encoding >> 1) == 0 ? targetName : readString(encoding >> 1);
file::copy({originPath, sourceName}, {targetPath, targetName});
uint32_t cksum = readChecksum();
uint32 cksum = readChecksum();
}
}
uint32_t cksum = checksum.value();
if(read() != (uint8_t)(cksum >> 0)) return false;
if(read() != (uint8_t)(cksum >> 8)) return false;
if(read() != (uint8_t)(cksum >> 16)) return false;
if(read() != (uint8_t)(cksum >> 24)) return false;
uint32 cksum = checksum.value();
if(read() != (uint8)(cksum >> 0)) return false;
if(read() != (uint8)(cksum >> 8)) return false;
if(read() != (uint8)(cksum >> 16)) return false;
if(read() != (uint8)(cksum >> 24)) return false;
fp.close();
return true;
@ -157,7 +157,7 @@ protected:
Hash::CRC32 checksum;
//create() functions
void ls(lstring& list, const string& path, const string& basepath) {
auto ls(lstring& list, const string& path, const string& basepath) -> void {
lstring paths = directory::folders(path);
for(auto& pathname : paths) {
list.append(string{path, pathname}.ltrim(basepath, 1L));
@ -170,14 +170,14 @@ protected:
}
}
void write(uint8_t data) {
auto write(uint8 data) -> void {
fp.write(data);
checksum.data(data);
}
void writeNumber(uint64_t data) {
auto writeNumber(uint64 data) -> void {
while(true) {
uint64_t x = data & 0x7f;
uint64 x = data & 0x7f;
data >>= 7;
if(data == 0) {
write(0x80 | x);
@ -188,12 +188,12 @@ protected:
}
}
void writeString(const string& text) {
unsigned length = text.length();
for(unsigned n = 0; n < length; n++) write(text[n]);
auto writeString(const string& text) -> void {
uint length = text.length();
for(uint n = 0; n < length; n++) write(text[n]);
}
void writeChecksum(uint32_t cksum) {
auto writeChecksum(uint32 cksum) -> void {
write(cksum >> 0);
write(cksum >> 8);
write(cksum >> 16);
@ -201,16 +201,16 @@ protected:
}
//apply() functions
uint8_t read() {
uint8_t data = fp.read();
auto read() -> uint8 {
uint8 data = fp.read();
checksum.data(data);
return data;
}
uint64_t readNumber() {
uint64_t data = 0, shift = 1;
auto readNumber() -> uint64 {
uint64 data = 0, shift = 1;
while(true) {
uint8_t x = read();
uint8 x = read();
data += (x & 0x7f) * shift;
if(x & 0x80) break;
shift <<= 7;
@ -219,7 +219,7 @@ protected:
return data;
}
string readString(unsigned length) {
auto readString(uint length) -> string {
string text;
text.resize(length + 1);
char* p = text.get();
@ -227,8 +227,8 @@ protected:
return text;
}
uint32_t readChecksum() {
uint32_t checksum = 0;
auto readChecksum() -> uint32 {
uint32 checksum = 0;
checksum |= read() << 0;
checksum |= read() << 8;
checksum |= read() << 16;

View File

@ -9,18 +9,18 @@
namespace nall {
struct bpspatch {
inline bool modify(const uint8_t* data, unsigned size);
inline void source(const uint8_t* data, unsigned size);
inline void target(uint8_t* data, unsigned size);
inline auto modify(const uint8* data, uint size) -> bool;
inline auto source(const uint8* data, uint size) -> void;
inline auto target(uint8* data, uint size) -> void;
inline bool modify(const string& filename);
inline bool source(const string& filename);
inline bool target(const string& filename);
inline auto modify(const string& filename) -> bool;
inline auto source(const string& filename) -> bool;
inline auto target(const string& filename) -> bool;
inline string metadata() const;
inline unsigned size() const;
inline auto metadata() const -> string;
inline auto size() const -> uint;
enum result : unsigned {
enum result : uint {
unknown,
success,
patch_too_small,
@ -32,39 +32,39 @@ struct bpspatch {
patch_checksum_invalid,
};
inline result apply();
inline auto apply() -> result;
protected:
enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
enum : uint { SourceRead, TargetRead, SourceCopy, TargetCopy };
filemap modifyFile;
const uint8_t* modifyData;
unsigned modifySize;
const uint8* modifyData;
uint modifySize;
filemap sourceFile;
const uint8_t* sourceData;
unsigned sourceSize;
const uint8* sourceData;
uint sourceSize;
filemap targetFile;
uint8_t* targetData;
unsigned targetSize;
uint8* targetData;
uint targetSize;
unsigned modifySourceSize;
unsigned modifyTargetSize;
unsigned modifyMarkupSize;
uint modifySourceSize;
uint modifyTargetSize;
uint modifyMarkupSize;
string metadataString;
};
bool bpspatch::modify(const uint8_t* data, unsigned size) {
auto bpspatch::modify(const uint8* data, uint size) -> bool {
if(size < 19) return false;
modifyData = data;
modifySize = size;
unsigned offset = 4;
auto decode = [&]() -> uint64_t {
uint64_t data = 0, shift = 1;
uint offset = 4;
auto decode = [&]() -> uint64 {
uint64 data = 0, shift = 1;
while(true) {
uint8_t x = modifyData[offset++];
uint8 x = modifyData[offset++];
data += (x & 0x7f) * shift;
if(x & 0x80) break;
shift <<= 7;
@ -78,35 +78,35 @@ bool bpspatch::modify(const uint8_t* data, unsigned size) {
modifyMarkupSize = decode();
char buffer[modifyMarkupSize + 1];
for(unsigned n = 0; n < modifyMarkupSize; n++) buffer[n] = modifyData[offset++];
for(uint n = 0; n < modifyMarkupSize; n++) buffer[n] = modifyData[offset++];
buffer[modifyMarkupSize] = 0;
metadataString = (const char*)buffer;
return true;
}
void bpspatch::source(const uint8_t* data, unsigned size) {
auto bpspatch::source(const uint8* data, uint size) -> void {
sourceData = data;
sourceSize = size;
}
void bpspatch::target(uint8_t* data, unsigned size) {
auto bpspatch::target(uint8* data, uint size) -> void {
targetData = data;
targetSize = size;
}
bool bpspatch::modify(const string& filename) {
auto bpspatch::modify(const string& filename) -> bool {
if(modifyFile.open(filename, filemap::mode::read) == false) return false;
return modify(modifyFile.data(), modifyFile.size());
}
bool bpspatch::source(const string& filename) {
auto bpspatch::source(const string& filename) -> bool {
if(sourceFile.open(filename, filemap::mode::read) == false) return false;
source(sourceFile.data(), sourceFile.size());
return true;
}
bool bpspatch::target(const string& filename) {
auto bpspatch::target(const string& filename) -> bool {
file fp;
if(fp.open(filename, file::mode::write) == false) return false;
fp.truncate(modifyTargetSize);
@ -117,30 +117,30 @@ bool bpspatch::target(const string& filename) {
return true;
}
string bpspatch::metadata() const {
auto bpspatch::metadata() const -> string {
return metadataString;
}
unsigned bpspatch::size() const {
auto bpspatch::size() const -> uint {
return modifyTargetSize;
}
bpspatch::result bpspatch::apply() {
auto bpspatch::apply() -> result {
if(modifySize < 19) return result::patch_too_small;
Hash::CRC32 modifyChecksum, targetChecksum;
unsigned modifyOffset = 0, sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0;
uint modifyOffset = 0, sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0;
auto read = [&]() -> uint8_t {
uint8_t data = modifyData[modifyOffset++];
auto read = [&]() -> uint8 {
uint8 data = modifyData[modifyOffset++];
modifyChecksum.data(data);
return data;
};
auto decode = [&]() -> uint64_t {
uint64_t data = 0, shift = 1;
auto decode = [&]() -> uint64 {
uint64 data = 0, shift = 1;
while(true) {
uint8_t x = read();
uint8 x = read();
data += (x & 0x7f) * shift;
if(x & 0x80) break;
shift <<= 7;
@ -149,7 +149,7 @@ bpspatch::result bpspatch::apply() {
return data;
};
auto write = [&](uint8_t data) {
auto write = [&](uint8 data) {
targetData[outputOffset++] = data;
targetChecksum.data(data);
};
@ -162,14 +162,14 @@ bpspatch::result bpspatch::apply() {
modifySourceSize = decode();
modifyTargetSize = decode();
modifyMarkupSize = decode();
for(unsigned n = 0; n < modifyMarkupSize; n++) read();
for(uint n = 0; n < modifyMarkupSize; n++) read();
if(modifySourceSize > sourceSize) return result::source_too_small;
if(modifyTargetSize > targetSize) return result::target_too_small;
while(modifyOffset < modifySize - 12) {
unsigned length = decode();
unsigned mode = length & 3;
uint length = decode();
uint mode = length & 3;
length = (length >> 2) + 1;
switch(mode) {
@ -181,7 +181,7 @@ bpspatch::result bpspatch::apply() {
break;
case SourceCopy:
case TargetCopy:
signed offset = decode();
int offset = decode();
bool negative = offset & 1;
offset >>= 1;
if(negative) offset = -offset;
@ -197,13 +197,13 @@ bpspatch::result bpspatch::apply() {
}
}
uint32_t modifySourceChecksum = 0, modifyTargetChecksum = 0, modifyModifyChecksum = 0;
for(unsigned n = 0; n < 32; n += 8) modifySourceChecksum |= read() << n;
for(unsigned n = 0; n < 32; n += 8) modifyTargetChecksum |= read() << n;
uint32_t checksum = modifyChecksum.value();
for(unsigned n = 0; n < 32; n += 8) modifyModifyChecksum |= read() << n;
uint32 modifySourceChecksum = 0, modifyTargetChecksum = 0, modifyModifyChecksum = 0;
for(uint n = 0; n < 32; n += 8) modifySourceChecksum |= read() << n;
for(uint n = 0; n < 32; n += 8) modifyTargetChecksum |= read() << n;
uint32 checksum = modifyChecksum.value();
for(uint n = 0; n < 32; n += 8) modifyModifyChecksum |= read() << n;
uint32_t sourceChecksum = Hash::CRC32(sourceData, modifySourceSize).value();
uint32 sourceChecksum = Hash::CRC32(sourceData, modifySourceSize).value();
if(sourceChecksum != modifySourceChecksum) return result::source_checksum_invalid;
if(targetChecksum.value() != modifyTargetChecksum) return result::target_checksum_invalid;

View File

@ -7,14 +7,14 @@ namespace nall {
struct bitvector {
bitvector() = default;
bitvector(unsigned size) { resize(size); }
bitvector(uint size) { resize(size); }
bitvector(const bitvector& source) { operator=(source); }
bitvector(bitvector&& source) { operator=(move(source)); }
~bitvector() { reset(); }
auto operator=(const bitvector& source) -> bitvector& {
bits = source.bits;
pool = (uint8_t*)memory::resize(pool, bytes());
pool = (uint8*)memory::resize(pool, bytes());
memory::copy(pool, source.pool, bytes());
return *this;
}
@ -29,10 +29,10 @@ struct bitvector {
explicit operator bool() const { return bits > 0; }
auto empty() const -> bool { return bits == 0; }
auto size() const -> unsigned { return bits; }
auto bytes() const -> unsigned { return (bits + 7) / 8; }
auto data() -> uint8_t* { return pool; }
auto data() const -> const uint8_t* { return pool; }
auto size() const -> uint { return bits; }
auto bytes() const -> uint { return (bits + 7) / 8; }
auto data() -> uint8* { return pool; }
auto data() const -> const uint8* { return pool; }
auto reset() -> void {
if(pool) free(pool);
@ -40,15 +40,15 @@ struct bitvector {
bits = 0;
}
auto resize(unsigned size) -> void {
unsigned from = bits;
auto resize(uint size) -> void {
uint from = bits;
bits = size;
for(unsigned n = size; n < from; n++) clear(n); //on reduce
pool = (uint8_t*)memory::resize(pool, bytes());
for(unsigned n = from; n < size; n++) clear(n); //on expand
for(uint n = size; n < from; n++) clear(n); //on reduce
pool = (uint8*)memory::resize(pool, bytes());
for(uint n = from; n < size; n++) clear(n); //on expand
}
auto get(unsigned position) const -> bool {
auto get(uint position) const -> bool {
return pool[position >> 3] & (0x80 >> (position & 7));
}
@ -58,60 +58,60 @@ struct bitvector {
auto set() -> void {
memory::fill(pool, bytes(), 0xff);
for(unsigned n = bits; n < bytes() * 8; n++) clear(n);
for(uint n = bits; n < bytes() * 8; n++) clear(n);
}
auto clear(unsigned position) -> void {
auto clear(uint position) -> void {
pool[position >> 3] &= ~(0x80 >> (position & 7));
}
auto set(unsigned position) -> void {
auto set(uint position) -> void {
pool[position >> 3] |= (0x80 >> (position & 7));
}
auto invert(unsigned position) -> void {
auto invert(uint position) -> void {
get(position) ? clear(position) : set(position);
}
auto set(unsigned position, bool value) -> void {
auto set(uint position, bool value) -> void {
value ? set(position) : clear(position);
}
struct reference {
reference(bitvector& self, unsigned position) : self(self), position(position) {}
reference(bitvector& self, uint position) : self(self), position(position) {}
operator bool() const { return self.get(position); }
auto operator=(bool value) -> reference& { self.set(position, value); return *this; }
protected:
bitvector& self;
unsigned position;
uint position;
};
auto operator[](unsigned position) -> reference {
auto operator[](uint position) -> reference {
return reference(*this, position);
}
auto operator[](unsigned position) const -> bool {
auto operator[](uint position) const -> bool {
return get(position);
}
struct iterator {
iterator(bitvector& self, unsigned position) : self(self), position(position) {}
iterator(bitvector& self, uint position) : self(self), position(position) {}
auto operator!=(const iterator& source) const -> bool { return position != source.position; }
auto operator++() -> iterator& { position++; return *this; }
auto operator*() -> reference { return self.operator[](position); }
protected:
bitvector& self;
unsigned position;
uint position;
};
auto begin() -> iterator { return iterator(*this, 0); }
auto end() -> iterator { return iterator(*this, bits); }
protected:
uint8_t* pool = nullptr;
unsigned bits = 0;
uint8* pool = nullptr;
uint bits = 0;
};
}

View File

@ -7,52 +7,55 @@
namespace nall { namespace Decode {
struct GZIP {
string filename;
uint8_t* data = nullptr;
unsigned size = 0;
inline bool decompress(const string& filename);
inline bool decompress(const uint8_t* data, unsigned size);
inline GZIP();
inline ~GZIP();
inline auto decompress(const string& filename) -> bool;
inline auto decompress(const uint8* data, uint size) -> bool;
string filename;
uint8* data = nullptr;
uint size = 0;
};
bool GZIP::decompress(const string& filename) {
GZIP::~GZIP() {
if(data) delete[] data;
}
auto GZIP::decompress(const string& filename) -> bool {
if(auto memory = file::read(filename)) {
return decompress(memory.data(), memory.size());
}
return false;
}
bool GZIP::decompress(const uint8_t* data, unsigned size) {
auto GZIP::decompress(const uint8* data, uint size) -> bool {
if(size < 18) return false;
if(data[0] != 0x1f) return false;
if(data[1] != 0x8b) return false;
unsigned cm = data[2];
unsigned flg = data[3];
unsigned mtime = data[4];
uint cm = data[2];
uint flg = data[3];
uint mtime = data[4];
mtime |= data[5] << 8;
mtime |= data[6] << 16;
mtime |= data[7] << 24;
unsigned xfl = data[8];
unsigned os = data[9];
unsigned p = 10;
unsigned isize = data[size - 4];
uint xfl = data[8];
uint os = data[9];
uint p = 10;
uint isize = data[size - 4];
isize |= data[size - 3] << 8;
isize |= data[size - 2] << 16;
isize |= data[size - 1] << 24;
filename = "";
if(flg & 0x04) { //FEXTRA
unsigned xlen = data[p + 0];
uint xlen = data[p + 0];
xlen |= data[p + 1] << 8;
p += 2 + xlen;
}
if(flg & 0x08) { //FNAME
char buffer[PATH_MAX];
for(unsigned n = 0; n < PATH_MAX; n++, p++) {
for(uint n = 0; n < PATH_MAX; n++, p++) {
buffer[n] = data[p];
if(data[p] == 0) break;
}
@ -73,13 +76,6 @@ bool GZIP::decompress(const uint8_t* data, unsigned size) {
return inflate(this->data, this->size, data + p, size - p - 8);
}
GZIP::GZIP() {
}
GZIP::~GZIP() {
if(data) delete[] data;
}
}}
#endif

View File

@ -6,16 +6,16 @@
namespace nall { namespace Decode {
namespace puff {
inline int puff(
inline auto puff(
unsigned char* dest, unsigned long* destlen,
unsigned char* source, unsigned long* sourcelen
);
) -> int;
}
inline bool inflate(
uint8_t* target, unsigned targetLength,
const uint8_t* source, unsigned sourceLength
) {
inline auto inflate(
uint8* target, uint targetLength,
const uint8* source, uint sourceLength
) -> bool {
unsigned long tl = targetLength, sl = sourceLength;
int result = puff::puff((unsigned char*)target, &tl, (unsigned char*)source, &sl);
return result == 0;
@ -23,7 +23,7 @@ inline bool inflate(
namespace puff {
enum {
enum : uint {
MAXBITS = 15,
MAXLCODES = 286,
MAXDCODES = 30,
@ -50,7 +50,7 @@ struct huffman {
short* symbol;
};
inline int bits(state* s, int need) {
inline auto bits(state* s, int need) -> int {
long val;
val = s->bitbuf;
@ -66,8 +66,8 @@ inline int bits(state* s, int need) {
return (int)(val & ((1L << need) - 1));
}
inline int stored(state* s) {
unsigned len;
inline auto stored(state* s) -> int {
uint len;
s->bitbuf = 0;
s->bitcnt = 0;
@ -91,7 +91,7 @@ inline int stored(state* s) {
return 0;
}
inline int decode(state* s, huffman* h) {
inline auto decode(state* s, huffman* h) -> int {
int len, code, first, count, index, bitbuf, left;
short* next;
@ -126,7 +126,7 @@ inline int decode(state* s, huffman* h) {
return -10;
}
inline int construct(huffman* h, short* length, int n) {
inline auto construct(huffman* h, short* length, int n) -> int {
int symbol, len, left;
short offs[MAXBITS + 1];
@ -151,9 +151,9 @@ inline int construct(huffman* h, short* length, int n) {
return left;
}
inline int codes(state* s, huffman* lencode, huffman* distcode) {
inline auto codes(state* s, huffman* lencode, huffman* distcode) -> int {
int symbol, len;
unsigned dist;
uint dist;
static const short lens[29] = {
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
@ -213,7 +213,7 @@ inline int codes(state* s, huffman* lencode, huffman* distcode) {
return 0;
}
inline int fixed(state* s) {
inline auto fixed(state* s) -> int {
static int virgin = 1;
static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
@ -243,7 +243,7 @@ inline int fixed(state* s) {
return codes(s, &lencode, &distcode);
}
inline int dynamic(state* s) {
inline auto dynamic(state* s) -> int {
int nlen, ndist, ncode, index, err;
short lengths[MAXCODES];
short lencnt[MAXBITS + 1], lensym[MAXLCODES];
@ -303,10 +303,10 @@ inline int dynamic(state* s) {
return codes(s, &lencode, &distcode);
}
inline int puff(
inline auto puff(
unsigned char* dest, unsigned long* destlen,
unsigned char* source, unsigned long* sourcelen
) {
) -> int {
state s;
int last, type, err;

View File

@ -7,75 +7,83 @@
namespace nall { namespace Decode {
struct PNG {
inline PNG();
inline ~PNG();
inline auto load(const string& filename) -> bool;
inline auto load(const uint8* sourceData, uint sourceSize) -> bool;
inline auto readbits(const uint8*& data) -> uint;
struct Info {
unsigned width;
unsigned height;
unsigned bitDepth;
uint width;
uint height;
uint bitDepth;
//colorType:
//0 = L (luma)
//2 = R,G,B
//3 = P (palette)
//4 = L,A
//6 = R,G,B,A
unsigned colorType;
unsigned compressionMethod;
unsigned filterType;
unsigned interlaceMethod;
uint colorType;
uint compressionMethod;
uint filterType;
uint interlaceMethod;
unsigned bytesPerPixel;
unsigned pitch;
uint bytesPerPixel;
uint pitch;
uint8_t palette[256][3];
uint8 palette[256][3];
} info;
uint8_t* data = nullptr;
unsigned size = 0;
uint8* data = nullptr;
uint size = 0;
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;
inline PNG();
inline ~PNG();
uint bitpos = 0;
protected:
enum class FourCC : unsigned {
enum class FourCC : uint {
IHDR = 0x49484452,
PLTE = 0x504c5445,
IDAT = 0x49444154,
IEND = 0x49454e44,
};
inline unsigned interlace(unsigned pass, unsigned index);
inline unsigned inflateSize();
inline bool deinterlace(const uint8_t*& inputData, unsigned pass);
inline bool filter(uint8_t* outputData, const uint8_t* inputData, unsigned width, unsigned height);
inline unsigned read(const uint8_t* data, unsigned length);
inline auto interlace(uint pass, uint index) -> uint;
inline auto inflateSize() -> uint;
inline auto deinterlace(const uint8*& inputData, uint pass) -> bool;
inline auto filter(uint8* outputData, const uint8* inputData, uint width, uint height) -> bool;
inline auto read(const uint8* data, uint length) -> uint;
};
bool PNG::load(const string& filename) {
PNG::PNG() {
}
PNG::~PNG() {
if(data) delete[] data;
}
auto PNG::load(const string& filename) -> bool {
if(auto memory = file::read(filename)) {
return load(memory.data(), memory.size());
}
return false;
}
bool PNG::load(const uint8_t* sourceData, unsigned sourceSize) {
auto PNG::load(const uint8* sourceData, uint sourceSize) -> bool {
if(sourceSize < 8) return false;
if(read(sourceData + 0, 4) != 0x89504e47) return false;
if(read(sourceData + 4, 4) != 0x0d0a1a0a) return false;
uint8_t* compressedData = nullptr;
unsigned compressedSize = 0;
uint8* compressedData = nullptr;
uint compressedSize = 0;
unsigned offset = 8;
uint offset = 8;
while(offset < sourceSize) {
unsigned length = read(sourceData + offset + 0, 4);
unsigned fourCC = read(sourceData + offset + 4, 4);
unsigned checksum = read(sourceData + offset + 8 + length, 4);
uint length = read(sourceData + offset + 0, 4);
uint fourCC = read(sourceData + offset + 4, 4);
uint checksum = read(sourceData + offset + 8 + length, 4);
if(fourCC == (unsigned)FourCC::IHDR) {
if(fourCC == (uint)FourCC::IHDR) {
info.width = read(sourceData + offset + 8, 4);
info.height = read(sourceData + offset + 12, 4);
info.bitDepth = read(sourceData + offset + 16, 1);
@ -108,30 +116,30 @@ bool PNG::load(const uint8_t* sourceData, unsigned sourceSize) {
info.pitch = (int)info.width * info.bytesPerPixel;
}
if(fourCC == (unsigned)FourCC::PLTE) {
if(fourCC == (uint)FourCC::PLTE) {
if(length % 3) return false;
for(unsigned n = 0, p = offset + 8; n < length / 3; n++) {
for(uint n = 0, p = offset + 8; n < length / 3; n++) {
info.palette[n][0] = sourceData[p++];
info.palette[n][1] = sourceData[p++];
info.palette[n][2] = sourceData[p++];
}
}
if(fourCC == (unsigned)FourCC::IDAT) {
compressedData = (uint8_t*)realloc(compressedData, compressedSize + length);
if(fourCC == (uint)FourCC::IDAT) {
compressedData = (uint8*)realloc(compressedData, compressedSize + length);
memcpy(compressedData + compressedSize, sourceData + offset + 8, length);
compressedSize += length;
}
if(fourCC == (unsigned)FourCC::IEND) {
if(fourCC == (uint)FourCC::IEND) {
break;
}
offset += 4 + 4 + length + 4;
}
unsigned interlacedSize = inflateSize();
uint8_t *interlacedData = new uint8_t[interlacedSize];
uint interlacedSize = inflateSize();
uint8 *interlacedData = new uint8[interlacedSize];
bool result = inflate(interlacedData, interlacedSize, compressedData + 2, compressedSize - 6);
free(compressedData);
@ -142,7 +150,7 @@ bool PNG::load(const uint8_t* sourceData, unsigned sourceSize) {
}
size = info.width * info.height * info.bytesPerPixel;
data = new uint8_t[size];
data = new uint8[size];
if(info.interlaceMethod == 0) {
if(filter(data, interlacedData, info.width, info.height) == false) {
@ -152,8 +160,8 @@ bool PNG::load(const uint8_t* sourceData, unsigned sourceSize) {
return false;
}
} else {
const uint8_t *passData = interlacedData;
for(unsigned pass = 0; pass < 7; pass++) {
const uint8* passData = interlacedData;
for(uint pass = 0; pass < 7; pass++) {
if(deinterlace(passData, pass) == false) {
delete[] interlacedData;
delete[] data;
@ -167,8 +175,8 @@ bool PNG::load(const uint8_t* sourceData, unsigned sourceSize) {
return true;
}
unsigned PNG::interlace(unsigned pass, unsigned index) {
static const unsigned data[7][4] = {
auto PNG::interlace(uint pass, uint index) -> uint {
static const uint data[7][4] = {
//x-distance, y-distance, x-origin, y-origin
{8, 8, 0, 0},
{8, 8, 4, 0},
@ -181,39 +189,39 @@ unsigned PNG::interlace(unsigned pass, unsigned index) {
return data[pass][index];
}
unsigned PNG::inflateSize() {
auto PNG::inflateSize() -> uint {
if(info.interlaceMethod == 0) {
return info.width * info.height * info.bytesPerPixel + info.height;
}
unsigned size = 0;
for(unsigned pass = 0; pass < 7; pass++) {
unsigned xd = interlace(pass, 0), yd = interlace(pass, 1);
unsigned xo = interlace(pass, 2), yo = interlace(pass, 3);
unsigned width = (info.width + (xd - xo - 1)) / xd;
unsigned height = (info.height + (yd - yo - 1)) / yd;
uint size = 0;
for(uint pass = 0; pass < 7; pass++) {
uint xd = interlace(pass, 0), yd = interlace(pass, 1);
uint xo = interlace(pass, 2), yo = interlace(pass, 3);
uint width = (info.width + (xd - xo - 1)) / xd;
uint height = (info.height + (yd - yo - 1)) / yd;
if(width == 0 || height == 0) continue;
size += width * height * info.bytesPerPixel + height;
}
return size;
}
bool PNG::deinterlace(const uint8_t*& inputData, unsigned pass) {
unsigned xd = interlace(pass, 0), yd = interlace(pass, 1);
unsigned xo = interlace(pass, 2), yo = interlace(pass, 3);
unsigned width = (info.width + (xd - xo - 1)) / xd;
unsigned height = (info.height + (yd - yo - 1)) / yd;
auto PNG::deinterlace(const uint8*& inputData, uint pass) -> bool {
uint xd = interlace(pass, 0), yd = interlace(pass, 1);
uint xo = interlace(pass, 2), yo = interlace(pass, 3);
uint width = (info.width + (xd - xo - 1)) / xd;
uint height = (info.height + (yd - yo - 1)) / yd;
if(width == 0 || height == 0) return true;
unsigned outputSize = width * height * info.bytesPerPixel;
uint8_t* outputData = new uint8_t[outputSize];
uint outputSize = width * height * info.bytesPerPixel;
uint8* outputData = new uint8[outputSize];
bool result = filter(outputData, inputData, width, height);
const uint8_t* rd = outputData;
for(unsigned y = yo; y < info.height; y += yd) {
uint8_t* wr = data + y * info.pitch;
for(unsigned x = xo; x < info.width; x += xd) {
for(unsigned b = 0; b < info.bytesPerPixel; b++) {
const uint8* rd = outputData;
for(uint y = yo; y < info.height; y += yd) {
uint8* wr = data + y * info.pitch;
for(uint x = xo; x < info.width; x += xd) {
for(uint b = 0; b < info.bytesPerPixel; b++) {
wr[x * info.bytesPerPixel + b] = *rd++;
}
}
@ -224,12 +232,12 @@ bool PNG::deinterlace(const uint8_t*& inputData, unsigned pass) {
return result;
}
bool PNG::filter(uint8_t* outputData, const uint8_t* inputData, unsigned width, unsigned height) {
uint8_t* wr = outputData;
const uint8_t* rd = inputData;
auto PNG::filter(uint8* outputData, const uint8* inputData, uint width, uint height) -> bool {
uint8* wr = outputData;
const uint8* rd = inputData;
int bpp = info.bytesPerPixel, pitch = width * bpp;
for(int y = 0; y < height; y++) {
uint8_t filter = *rd++;
uint8 filter = *rd++;
switch(filter) {
case 0x00: //None
@ -255,7 +263,7 @@ bool PNG::filter(uint8_t* outputData, const uint8_t* inputData, unsigned width,
short a = x - bpp < 0 ? 0 : wr[x - bpp];
short b = y - 1 < 0 ? 0 : wr[x - pitch];
wr[x] = rd[x] + (uint8_t)((a + b) / 2);
wr[x] = rd[x] + (uint8)((a + b) / 2);
}
break;
@ -270,7 +278,7 @@ bool PNG::filter(uint8_t* outputData, const uint8_t* inputData, unsigned width,
short pb = p > b ? p - b : b - p;
short pc = p > c ? p - c : c - p;
uint8_t paeth = (uint8_t)((pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c);
uint8 paeth = (uint8)((pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c);
wr[x] = rd[x] + paeth;
}
@ -287,14 +295,14 @@ bool PNG::filter(uint8_t* outputData, const uint8_t* inputData, unsigned width,
return true;
}
unsigned PNG::read(const uint8_t* data, unsigned length) {
unsigned result = 0;
auto PNG::read(const uint8* data, uint length) -> uint {
uint result = 0;
while(length--) result = (result << 8) | (*data++);
return result;
}
unsigned PNG::readbits(const uint8_t*& data) {
unsigned result = 0;
auto PNG::readbits(const uint8*& data) -> uint {
uint result = 0;
switch(info.bitDepth) {
case 1:
result = (*data >> bitpos) & 1;
@ -322,13 +330,6 @@ unsigned PNG::readbits(const uint8_t*& data) {
return result;
}
PNG::PNG() {
}
PNG::~PNG() {
if(data) delete[] data;
}
}}
#endif

View File

@ -11,14 +11,18 @@ namespace nall { namespace Decode {
struct ZIP {
struct File {
string name;
const uint8_t* data;
unsigned size;
unsigned csize;
unsigned cmode; //0 = uncompressed, 8 = deflate
unsigned crc32;
const uint8* data;
uint size;
uint csize;
uint cmode; //0 = uncompressed, 8 = deflate
uint crc32;
};
inline bool open(const string& filename) {
~ZIP() {
close();
}
auto open(const string& filename) -> bool {
close();
if(fm.open(filename, filemap::mode::read) == false) return false;
if(open(fm.data(), fm.size()) == false) {
@ -28,7 +32,7 @@ struct ZIP {
return true;
}
inline bool open(const uint8_t* data, unsigned size) {
auto open(const uint8* data, uint size) -> bool {
if(size < 22) return false;
filedata = data;
@ -36,19 +40,19 @@ struct ZIP {
file.reset();
const uint8_t* footer = data + size - 22;
const uint8* footer = data + size - 22;
while(true) {
if(footer <= data + 22) return false;
if(read(footer, 4) == 0x06054b50) {
unsigned commentlength = read(footer + 20, 2);
uint commentlength = read(footer + 20, 2);
if(footer + 22 + commentlength == data + size) break;
}
footer--;
}
const uint8_t* directory = data + read(footer + 16, 4);
const uint8* directory = data + read(footer + 16, 4);
while(true) {
unsigned signature = read(directory + 0, 4);
uint signature = read(directory + 0, 4);
if(signature != 0x02014b50) break;
File file;
@ -57,9 +61,9 @@ struct ZIP {
file.csize = read(directory + 20, 4);
file.size = read(directory + 24, 4);
unsigned namelength = read(directory + 28, 2);
unsigned extralength = read(directory + 30, 2);
unsigned commentlength = read(directory + 32, 2);
uint namelength = read(directory + 28, 2);
uint extralength = read(directory + 30, 2);
uint commentlength = read(directory + 32, 2);
char* filename = new char[namelength + 1];
memcpy(filename, directory + 46, namelength);
@ -67,9 +71,9 @@ struct ZIP {
file.name = filename;
delete[] filename;
unsigned offset = read(directory + 42, 4);
unsigned offsetNL = read(data + offset + 26, 2);
unsigned offsetEL = read(data + offset + 28, 2);
uint offset = read(directory + 42, 4);
uint offsetNL = read(data + offset + 26, 2);
uint offsetEL = read(data + offset + 28, 2);
file.data = data + offset + 30 + offsetNL + offsetEL;
directory += 46 + namelength + extralength + commentlength;
@ -80,8 +84,8 @@ struct ZIP {
return true;
}
inline vector<uint8_t> extract(File& file) {
vector<uint8_t> buffer;
auto extract(File& file) -> vector<uint8> {
vector<uint8> buffer;
if(file.cmode == 0) {
buffer.resize(file.size);
@ -98,21 +102,17 @@ struct ZIP {
return buffer;
}
inline void close() {
auto close() -> void {
if(fm.open()) fm.close();
}
~ZIP() {
close();
}
protected:
filemap fm;
const uint8_t* filedata;
unsigned filesize;
const uint8* filedata;
uint filesize;
unsigned read(const uint8_t* data, unsigned size) {
unsigned result = 0, shift = 0;
auto read(const uint8* data, uint size) -> uint {
uint result = 0, shift = 0;
while(size--) { result |= *data++ << shift; shift += 8; }
return result;
}

View File

@ -7,7 +7,7 @@ namespace nall {
template<typename T> struct function;
template<typename R, typename... P> struct function<R (P...)> {
template<typename R, typename... P> struct function<auto (P...) -> R> {
//value = true if auto L::operator()(P...) -> R exists
template<typename L> struct is_compatible {
template<typename T> static auto exists(T*) -> const typename is_same<R, decltype(declval<T>().operator()(declval<P>()...))>::type;

View File

@ -4,26 +4,24 @@ namespace nall {
namespace mosaic {
struct bitstream {
filemap fp;
uint8_t* data = nullptr;
unsigned size = 0;
bool readonly = false;
bool endian = 1;
~bitstream() {
close();
}
bool read(uint64_t addr) const {
auto read(uint64 addr) const -> bool {
if(data == nullptr || (addr >> 3) >= size) return 0;
unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
uint mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
return data[addr >> 3] & mask;
}
void write(uint64_t addr, bool value) {
auto write(uint64 addr, bool value) -> void {
if(data == nullptr || readonly == true || (addr >> 3) >= size) return;
unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
uint mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
if(value == 0) data[addr >> 3] &= ~mask;
if(value == 1) data[addr >> 3] |= mask;
}
bool open(const string& filename) {
auto open(const string& filename) -> bool {
readonly = false;
if(fp.open(filename, filemap::mode::readwrite) == false) {
readonly = true;
@ -36,17 +34,16 @@ struct bitstream {
return true;
}
void close() {
auto close() -> void {
fp.close();
data = nullptr;
}
bitstream() {
}
~bitstream() {
close();
}
filemap fp;
uint8* data = nullptr;
uint size = 0;
bool readonly = false;
bool endian = 1;
};
}

View File

@ -4,54 +4,60 @@ namespace nall {
namespace mosaic {
struct context {
unsigned offset;
unsigned width;
unsigned height;
unsigned count;
context() {
reset();
}
bool endian; //0 = lsb, 1 = msb
bool order; //0 = linear, 1 = planar
unsigned depth; //1 - 24bpp
unsigned blockWidth;
unsigned blockHeight;
unsigned blockStride;
unsigned blockOffset;
vector<unsigned> block;
unsigned tileWidth;
unsigned tileHeight;
unsigned tileStride;
unsigned tileOffset;
vector<unsigned> tile;
unsigned mosaicWidth;
unsigned mosaicHeight;
unsigned mosaicStride;
unsigned mosaicOffset;
vector<unsigned> mosaic;
unsigned paddingWidth;
unsigned paddingHeight;
unsigned paddingColor;
vector<unsigned> palette;
unsigned objectWidth() const { return blockWidth * tileWidth * mosaicWidth + paddingWidth; }
unsigned objectHeight() const { return blockHeight * tileHeight * mosaicHeight + paddingHeight; }
unsigned objectSize() const {
unsigned size = blockStride * tileWidth * tileHeight * mosaicWidth * mosaicHeight
+ blockOffset * tileHeight * mosaicWidth * mosaicHeight
+ tileStride * mosaicWidth * mosaicHeight
+ tileOffset * mosaicHeight;
auto objectWidth() const -> uint { return blockWidth * tileWidth * mosaicWidth + paddingWidth; }
auto objectHeight() const -> uint { return blockHeight * tileHeight * mosaicHeight + paddingHeight; }
auto objectSize() const -> uint {
uint size = blockStride * tileWidth * tileHeight * mosaicWidth * mosaicHeight
+ blockOffset * tileHeight * mosaicWidth * mosaicHeight
+ tileStride * mosaicWidth * mosaicHeight
+ tileOffset * mosaicHeight;
return max(1u, size);
}
unsigned eval(const string& expression) {
auto reset() -> void {
offset = 0;
width = 0;
height = 0;
count = 0;
endian = 1;
order = 0;
depth = 1;
blockWidth = 1;
blockHeight = 1;
blockStride = 0;
blockOffset = 0;
block.reset();
tileWidth = 1;
tileHeight = 1;
tileStride = 0;
tileOffset = 0;
tile.reset();
mosaicWidth = 1;
mosaicHeight = 1;
mosaicStride = 0;
mosaicOffset = 0;
mosaic.reset();
paddingWidth = 0;
paddingHeight = 0;
paddingColor = 0;
palette.reset();
}
auto eval(const string& expression) -> uint {
if(auto result = Eval::integer(expression)) return result();
return 0u;
}
void eval(vector<unsigned>& buffer, const string& expression_) {
auto eval(vector<uint>& buffer, const string& expression_) -> void {
string expression = expression_;
bool function = false;
for(auto& c : expression) {
@ -68,13 +74,13 @@ struct context {
lstring part = item.split(") ", 1L);
lstring args = part[0].split(";", 3L).strip();
unsigned length = eval(args(0, "0"));
unsigned offset = eval(args(1, "0"));
unsigned stride = eval(args(2, "0"));
uint length = eval(args(0, "0"));
uint offset = eval(args(1, "0"));
uint stride = eval(args(2, "0"));
if(args.size() < 2) offset = buffer.size();
if(args.size() < 3) stride = 1;
for(unsigned n = 0; n < length; n++) {
for(uint n = 0; n < length; n++) {
string fn = part[1];
fn.replace("n", string{n});
fn.replace("o", string{offset});
@ -84,7 +90,7 @@ struct context {
offset += stride;
}
} else if(item.match("base64*")) {
unsigned offset = 0;
uint offset = 0;
item.ltrim("base64", 1L);
if(item.match("(?*) *")) {
item.ltrim("(", 1L);
@ -110,7 +116,7 @@ struct context {
}
}
void parse(const string& data) {
auto parse(const string& data) -> void {
reset();
lstring lines = data.split("\n");
@ -154,14 +160,15 @@ struct context {
sanitize();
}
bool load(const string& filename) {
string filedata = string::read(filename);
if(filedata.empty()) return false;
parse(filedata);
return true;
auto load(const string& filename) -> bool {
if(auto filedata = string::read(filename)) {
parse(filedata);
return true;
}
return false;
}
void sanitize() {
auto sanitize() -> void {
if(depth < 1) depth = 1;
if(depth > 24) depth = 24;
@ -179,43 +186,37 @@ struct context {
for(auto& color : palette) color |= 255u << 24;
}
void reset() {
offset = 0;
width = 0;
height = 0;
count = 0;
uint offset;
uint width;
uint height;
uint count;
endian = 1;
order = 0;
depth = 1;
bool endian; //0 = lsb, 1 = msb
bool order; //0 = linear, 1 = planar
uint depth; //1 - 24bpp
blockWidth = 1;
blockHeight = 1;
blockStride = 0;
blockOffset = 0;
block.reset();
uint blockWidth;
uint blockHeight;
uint blockStride;
uint blockOffset;
vector<uint> block;
tileWidth = 1;
tileHeight = 1;
tileStride = 0;
tileOffset = 0;
tile.reset();
uint tileWidth;
uint tileHeight;
uint tileStride;
uint tileOffset;
vector<uint> tile;
mosaicWidth = 1;
mosaicHeight = 1;
mosaicStride = 0;
mosaicOffset = 0;
mosaic.reset();
uint mosaicWidth;
uint mosaicHeight;
uint mosaicStride;
uint mosaicOffset;
vector<uint> mosaic;
paddingWidth = 0;
paddingHeight = 0;
paddingColor = 0;
palette.reset();
}
context() {
reset();
}
uint paddingWidth;
uint paddingHeight;
uint paddingColor;
vector<uint> palette;
};
}

View File

@ -4,77 +4,72 @@ namespace nall {
namespace mosaic {
struct parser {
image canvas;
//export from bitstream to canvas
void load(bitstream& stream, uint64_t offset, context& ctx, unsigned width, unsigned height) {
auto load(bitstream& stream, uint64 offset, context& ctx, uint width, uint height) -> void {
canvas.allocate(width, height);
canvas.fill(ctx.paddingColor);
parse(1, stream, offset, ctx, width, height);
}
//import from canvas to bitstream
bool save(bitstream& stream, uint64_t offset, context& ctx) {
auto save(bitstream& stream, uint64_t offset, context& ctx) -> bool {
if(stream.readonly) return false;
parse(0, stream, offset, ctx, canvas.width(), canvas.height());
return true;
}
inline parser() : canvas(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0) {
}
private:
uint32_t read(unsigned x, unsigned y) const {
unsigned addr = y * canvas.width() + x;
auto read(uint x, uint y) const -> uint32 {
uint addr = y * canvas.width() + x;
if(addr >= canvas.width() * canvas.height()) return 0u;
uint32_t *buffer = (uint32_t*)canvas.data();
auto buffer = (uint32*)canvas.data();
return buffer[addr];
}
void write(unsigned x, unsigned y, uint32_t data) {
unsigned addr = y * canvas.width() + x;
auto write(uint x, uint y, uint32_t data) -> void {
uint addr = y * canvas.width() + x;
if(addr >= canvas.width() * canvas.height()) return;
uint32_t *buffer = (uint32_t*)canvas.data();
auto buffer = (uint32*)canvas.data();
buffer[addr] = data;
}
void parse(bool load, bitstream& stream, uint64_t offset, context& ctx, unsigned width, unsigned height) {
auto parse(bool load, bitstream& stream, uint64 offset, context& ctx, uint width, uint height) -> void {
stream.endian = ctx.endian;
unsigned canvasWidth = width / (ctx.mosaicWidth * ctx.tileWidth * ctx.blockWidth + ctx.paddingWidth);
unsigned canvasHeight = height / (ctx.mosaicHeight * ctx.tileHeight * ctx.blockHeight + ctx.paddingHeight);
unsigned bitsPerBlock = ctx.depth * ctx.blockWidth * ctx.blockHeight;
uint canvasWidth = width / (ctx.mosaicWidth * ctx.tileWidth * ctx.blockWidth + ctx.paddingWidth);
uint canvasHeight = height / (ctx.mosaicHeight * ctx.tileHeight * ctx.blockHeight + ctx.paddingHeight);
uint bitsPerBlock = ctx.depth * ctx.blockWidth * ctx.blockHeight;
unsigned objectOffset = 0;
for(unsigned objectY = 0; objectY < canvasHeight; objectY++) {
for(unsigned objectX = 0; objectX < canvasWidth; objectX++) {
uint objectOffset = 0;
for(uint objectY = 0; objectY < canvasHeight; objectY++) {
for(uint objectX = 0; objectX < canvasWidth; objectX++) {
if(objectOffset >= ctx.count && ctx.count > 0) break;
unsigned objectIX = objectX * ctx.objectWidth();
unsigned objectIY = objectY * ctx.objectHeight();
uint objectIX = objectX * ctx.objectWidth();
uint objectIY = objectY * ctx.objectHeight();
objectOffset++;
unsigned mosaicOffset = 0;
for(unsigned mosaicY = 0; mosaicY < ctx.mosaicHeight; mosaicY++) {
for(unsigned mosaicX = 0; mosaicX < ctx.mosaicWidth; mosaicX++) {
unsigned mosaicData = ctx.mosaic(mosaicOffset, mosaicOffset);
unsigned mosaicIX = (mosaicData % ctx.mosaicWidth) * (ctx.tileWidth * ctx.blockWidth);
unsigned mosaicIY = (mosaicData / ctx.mosaicWidth) * (ctx.tileHeight * ctx.blockHeight);
uint mosaicOffset = 0;
for(uint mosaicY = 0; mosaicY < ctx.mosaicHeight; mosaicY++) {
for(uint mosaicX = 0; mosaicX < ctx.mosaicWidth; mosaicX++) {
uint mosaicData = ctx.mosaic(mosaicOffset, mosaicOffset);
uint mosaicIX = (mosaicData % ctx.mosaicWidth) * (ctx.tileWidth * ctx.blockWidth);
uint mosaicIY = (mosaicData / ctx.mosaicWidth) * (ctx.tileHeight * ctx.blockHeight);
mosaicOffset++;
unsigned tileOffset = 0;
for(unsigned tileY = 0; tileY < ctx.tileHeight; tileY++) {
for(unsigned tileX = 0; tileX < ctx.tileWidth; tileX++) {
unsigned tileData = ctx.tile(tileOffset, tileOffset);
unsigned tileIX = (tileData % ctx.tileWidth) * ctx.blockWidth;
unsigned tileIY = (tileData / ctx.tileWidth) * ctx.blockHeight;
uint tileOffset = 0;
for(uint tileY = 0; tileY < ctx.tileHeight; tileY++) {
for(uint tileX = 0; tileX < ctx.tileWidth; tileX++) {
uint tileData = ctx.tile(tileOffset, tileOffset);
uint tileIX = (tileData % ctx.tileWidth) * ctx.blockWidth;
uint tileIY = (tileData / ctx.tileWidth) * ctx.blockHeight;
tileOffset++;
unsigned blockOffset = 0;
for(unsigned blockY = 0; blockY < ctx.blockHeight; blockY++) {
for(unsigned blockX = 0; blockX < ctx.blockWidth; blockX++) {
uint blockOffset = 0;
for(uint blockY = 0; blockY < ctx.blockHeight; blockY++) {
for(uint blockX = 0; blockX < ctx.blockWidth; blockX++) {
if(load) {
unsigned palette = 0;
for(unsigned n = 0; n < ctx.depth; n++) {
unsigned index = blockOffset++;
uint palette = 0;
for(uint n = 0; n < ctx.depth; n++) {
uint index = blockOffset++;
if(ctx.order == 1) index = (index % ctx.depth) * ctx.blockWidth * ctx.blockHeight + (index / ctx.depth);
palette |= stream.read(offset + ctx.block(index, index)) << n;
}
@ -90,8 +85,8 @@ private:
objectIY + mosaicIY + tileIY + blockY
);
for(unsigned n = 0; n < ctx.depth; n++) {
unsigned index = blockOffset++;
for(uint n = 0; n < ctx.depth; n++) {
uint index = blockOffset++;
if(ctx.order == 1) index = (index % ctx.depth) * ctx.blockWidth * ctx.blockHeight + (index / ctx.depth);
stream.write(offset + ctx.block(index, index), palette & 1);
palette >>= 1;
@ -118,6 +113,8 @@ private:
offset += ctx.mosaicOffset;
} //objectY
}
image canvas;
};
}

View File

@ -5,17 +5,17 @@ namespace nall {
#define autostream(...) (*makestream(__VA_ARGS__))
inline std::unique_ptr<stream> makestream(const string& path) {
inline auto makestream(const string& path) -> std::unique_ptr<stream> {
if(path.iendsWith(".gz")) return std::unique_ptr<stream>(new gzipstream(filestream{path}));
if(path.iendsWith(".zip")) return std::unique_ptr<stream>(new zipstream(filestream{path}));
return std::unique_ptr<stream>(new mmapstream(path));
}
inline std::unique_ptr<stream> makestream(uint8_t* data, unsigned size) {
inline auto makestream(uint8* data, uint size) -> std::unique_ptr<stream> {
return std::unique_ptr<stream>(new memorystream(data, size));
}
inline std::unique_ptr<stream> makestream(const uint8_t* data, unsigned size) {
inline auto makestream(const uint8* data, uint size) -> std::unique_ptr<stream> {
return std::unique_ptr<stream>(new memorystream(data, size));
}

View File

@ -9,18 +9,6 @@ struct filestream : stream {
using stream::read;
using stream::write;
bool seekable() const { return true; }
bool readable() const { return true; }
bool writable() const { return pwritable; }
bool randomaccess() const { return false; }
unsigned size() const { return pfile.size(); }
unsigned offset() const { return pfile.offset(); }
void seek(unsigned offset) const { pfile.seek(offset); }
uint8_t read() const { return pfile.read(); }
void write(uint8_t data) const { pfile.write(data); }
filestream(const string& filename) {
pfile.open(filename, file::mode::readwrite);
pwritable = pfile.open();
@ -32,6 +20,18 @@ struct filestream : stream {
pwritable = mode == file::mode::write || mode == file::mode::readwrite;
}
auto seekable() const -> bool { return true; }
auto readable() const -> bool { return true; }
auto writable() const -> bool { return pwritable; }
auto randomaccess() const -> bool { return false; }
auto size() const -> uint { return pfile.size(); }
auto offset() const -> uint { return pfile.offset(); }
auto seek(unsigned offset) const -> void { pfile.seek(offset); }
auto read() const -> uint8 { return pfile.read(); }
auto write(uint8_t data) const -> void { pfile.write(data); }
private:
mutable file pfile;
bool pwritable;

View File

@ -10,14 +10,14 @@ struct gzipstream : memorystream {
using stream::write;
gzipstream(const stream& stream) {
unsigned size = stream.size();
uint8_t *data = new uint8_t[size];
uint size = stream.size();
auto data = new uint8[size];
stream.read(data, size);
Decode::GZIP archive;
bool result = archive.decompress(data, size);
delete[] data;
if(result == false) return;
if(!result) return;
psize = archive.size;
pdata = new uint8_t[psize];

View File

@ -9,37 +9,41 @@ struct memorystream : stream {
using stream::read;
using stream::write;
bool seekable() const { return true; }
bool readable() const { return true; }
bool writable() const { return pwritable; }
bool randomaccess() const { return true; }
memorystream() = default;
uint8_t* data() const { return pdata; }
unsigned size() const { return psize; }
unsigned offset() const { return poffset; }
void seek(unsigned offset) const { poffset = offset; }
uint8_t read() const { return pdata[poffset++]; }
void write(uint8_t data) const { pdata[poffset++] = data; }
uint8_t read(unsigned offset) const { return pdata[offset]; }
void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
memorystream() : pdata(nullptr), psize(0), poffset(0), pwritable(true) {}
memorystream(uint8_t* data, unsigned size) {
pdata = data, psize = size, poffset = 0;
memorystream(uint8* data, uint size) {
pdata = data;
psize = size;
pwritable = true;
}
memorystream(const uint8_t* data, unsigned size) {
pdata = (uint8_t*)data, psize = size, poffset = 0;
memorystream(const uint8* data, uint size) {
pdata = (uint8*)data;
psize = size;
pwritable = false;
}
auto seekable() const -> bool { return true; }
auto readable() const -> bool { return true; }
auto writable() const -> bool { return pwritable; }
auto randomaccess() const -> bool { return true; }
auto data() const -> uint8* { return pdata; }
auto size() const -> uint { return psize; }
auto offset() const -> uint { return poffset; }
auto seek(uint offset) const -> void { poffset = offset; }
auto read() const -> uint8 { return pdata[poffset++]; }
auto write(uint8 data) const -> void { pdata[poffset++] = data; }
auto read(uint offset) const -> uint8 { return pdata[offset]; }
auto write(uint offset, uint8 data) const -> void { pdata[offset] = data; }
protected:
mutable uint8_t* pdata;
mutable unsigned psize, poffset, pwritable;
mutable uint8* pdata = nullptr;
mutable uint psize = 0;
mutable uint poffset = 0;
mutable bool pwritable = false;
};
}

View File

@ -9,32 +9,34 @@ struct mmapstream : stream {
using stream::read;
using stream::write;
bool seekable() const { return true; }
bool readable() const { return true; }
bool writable() const { return pwritable; }
bool randomaccess() const { return true; }
unsigned size() const { return pmmap.size(); }
unsigned offset() const { return poffset; }
void seek(unsigned offset) const { poffset = offset; }
uint8_t read() const { return pdata[poffset++]; }
void write(uint8_t data) const { pdata[poffset++] = data; }
uint8_t read(unsigned offset) const { return pdata[offset]; }
void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
mmapstream(const string& filename) {
pmmap.open(filename, filemap::mode::readwrite);
pwritable = pmmap.open();
if(!pwritable) pmmap.open(filename, filemap::mode::read);
pdata = pmmap.data(), poffset = 0;
pdata = pmmap.data();
poffset = 0;
}
auto seekable() const -> bool { return true; }
auto readable() const -> bool { return true; }
auto writable() const -> bool { return pwritable; }
auto randomaccess() const -> bool { return true; }
auto size() const -> uint { return pmmap.size(); }
auto offset() const -> uint { return poffset; }
auto seek(unsigned offset) const -> void { poffset = offset; }
auto read() const -> uint8 { return pdata[poffset++]; }
auto write(uint8 data) const -> void { pdata[poffset++] = data; }
auto read(uint offset) const -> uint8 { return pdata[offset]; }
auto write(uint offset, uint8 data) const -> void { pdata[offset] = data; }
private:
mutable filemap pmmap;
mutable uint8_t* pdata;
mutable unsigned pwritable, poffset;
mutable uint8* pdata = nullptr;
mutable uint poffset = 0;
mutable bool pwritable = false;
};
}

View File

@ -4,95 +4,96 @@
namespace nall {
struct stream {
virtual bool seekable() const = 0;
virtual bool readable() const = 0;
virtual bool writable() const = 0;
virtual bool randomaccess() const = 0;
stream() = default;
virtual ~stream() = default;
virtual uint8_t* data() const { return nullptr; }
virtual unsigned size() const = 0;
virtual unsigned offset() const = 0;
virtual void seek(unsigned offset) const = 0;
stream(const stream&) = delete;
auto operator=(const stream&) -> stream& = delete;
virtual uint8_t read() const = 0;
virtual void write(uint8_t data) const = 0;
virtual auto seekable() const -> bool = 0;
virtual auto readable() const -> bool = 0;
virtual auto writable() const -> bool = 0;
virtual auto randomaccess() const -> bool = 0;
virtual uint8_t read(unsigned) const { return 0; }
virtual void write(unsigned, uint8_t) const {}
virtual auto data() const -> uint8* { return nullptr; }
virtual auto size() const -> uint = 0;
virtual auto offset() const -> uint = 0;
virtual auto seek(unsigned offset) const -> void = 0;
operator bool() const {
virtual auto read() const -> uint8 = 0;
virtual auto write(uint8_t data) const -> void = 0;
virtual auto read(uint) const -> uint8 { return 0; }
virtual auto write(uint, uint8) const -> void {}
explicit operator bool() const {
return size();
}
bool empty() const {
auto empty() const -> bool {
return size() == 0;
}
bool end() const {
auto end() const -> bool {
return offset() >= size();
}
uintmax_t readl(unsigned length = 1) const {
uintmax_t data = 0, shift = 0;
auto readl(uint length = 1) const -> uintmax {
uintmax data = 0, shift = 0;
while(length--) { data |= read() << shift; shift += 8; }
return data;
}
uintmax_t readm(unsigned length = 1) const {
uintmax_t data = 0;
auto readm(uint length = 1) const -> uintmax {
uintmax data = 0;
while(length--) data = (data << 8) | read();
return data;
}
void read(uint8_t* data, unsigned length) const {
auto read(uint8* data, uint length) const -> void {
while(length--) *data++ = read();
}
string text() const {
auto text() const -> string {
string buffer;
buffer.resize(size());
seek(0);
read((uint8_t*)buffer.data(), size());
read((uint8*)buffer.get(), size());
return buffer;
}
void writel(uintmax_t data, unsigned length = 1) const {
auto writel(uintmax data, uint length = 1) const -> void {
while(length--) {
write(data);
data >>= 8;
}
}
void writem(uintmax_t data, unsigned length = 1) const {
uintmax_t shift = 8 * length;
auto writem(uintmax data, uint length = 1) const -> void {
uintmax shift = 8 * length;
while(length--) {
shift -= 8;
write(data >> shift);
}
}
void write(const uint8_t* data, unsigned length) const {
auto write(const uint8* data, uint length) const -> void {
while(length--) write(*data++);
}
struct byte {
operator uint8_t() const { return s.read(offset); }
byte& operator=(uint8_t data) { s.write(offset, data); return *this; }
byte(const stream& s, unsigned offset) : s(s), offset(offset) {}
byte(const stream& s, uint offset) : s(s), offset(offset) {}
operator uint8() const { return s.read(offset); }
auto operator=(uint8_t data) -> byte& { s.write(offset, data); return *this; }
private:
const stream& s;
const unsigned offset;
const uint offset;
};
byte operator[](unsigned offset) const {
auto operator[](uint offset) const -> byte {
return byte(*this, offset);
}
stream() {}
virtual ~stream() {}
stream(const stream&) = delete;
stream& operator=(const stream&) = delete;
};
}

View File

@ -10,28 +10,29 @@ struct vectorstream : stream {
using stream::read;
using stream::write;
bool seekable() const { return true; }
bool readable() const { return true; }
bool writable() const { return pwritable; }
bool randomaccess() const { return true; }
vectorstream(vector<uint8>& memory) : memory(memory), pwritable(true) {}
vectorstream(const vector<uint8>& memory) : memory((vector<uint8>&)memory), pwritable(false) {}
uint8_t* data() const { return memory.data(); }
unsigned size() const { return memory.size(); }
unsigned offset() const { return poffset; }
void seek(unsigned offset) const { poffset = offset; }
auto seekable() const -> bool { return true; }
auto readable() const -> bool { return true; }
auto writable() const -> bool { return pwritable; }
auto randomaccess() const -> bool { return true; }
uint8_t read() const { return memory[poffset++]; }
void write(uint8_t data) const { memory[poffset++] = data; }
auto data() const -> uint8* { return memory.data(); }
auto size() const -> uint { return memory.size(); }
auto offset() const -> uint { return poffset; }
auto seek(unsigned offset) const -> void { poffset = offset; }
uint8_t read(unsigned offset) const { return memory[offset]; }
void write(unsigned offset, uint8_t data) const { memory[offset] = data; }
auto read() const -> uint8 { return memory[poffset++]; }
auto write(uint8 data) const -> void { memory[poffset++] = data; }
vectorstream(vector<uint8_t>& memory) : memory(memory), poffset(0), pwritable(true) {}
vectorstream(const vector<uint8_t>& memory) : memory((vector<uint8_t>&)memory), poffset(0), pwritable(false) {}
auto read(uint offset) const -> uint8 { return memory[offset]; }
auto write(uint offset, uint8 data) const -> void { memory[offset] = data; }
protected:
vector<uint8_t>& memory;
mutable unsigned poffset, pwritable;
vector<uint8>& memory;
mutable uint poffset = 0;
mutable bool pwritable = false;
};
}

View File

@ -10,8 +10,8 @@ struct zipstream : memorystream {
using stream::write;
zipstream(const stream& stream, const string& filter = "*") {
unsigned size = stream.size();
uint8_t* data = new uint8_t[size];
uint size = stream.size();
auto data = new uint8[size];
stream.read(data, size);
Decode::ZIP archive;

View File

@ -13,18 +13,18 @@ namespace nall {
#define RelNear 1
struct detour {
static bool insert(const string& moduleName, const string& functionName, void*& source, void* target);
static bool remove(const string& moduleName, const string& functionName, void*& source);
static auto insert(const string& moduleName, const string& functionName, void*& source, void* target) -> bool;
static auto remove(const string& moduleName, const string& functionName, void*& source) -> bool;
protected:
static unsigned length(const uint8_t* function);
static unsigned mirror(uint8_t* target, const uint8_t* source);
static auto length(const uint8* function) -> uint;
static auto mirror(uint8* target, const uint8* source) -> uint;
struct opcode {
uint16_t prefix;
unsigned length;
unsigned mode;
uint16_t modify;
uint16 prefix;
uint length;
uint mode;
uint16 modify;
};
static opcode opcodes[];
};
@ -33,61 +33,61 @@ protected:
//* fs:, gs: should force another opcode copy
//* conditional branches within +5-byte range should fail
detour::opcode detour::opcodes[] = {
{ 0x50, 1 }, //push eax
{ 0x51, 1 }, //push ecx
{ 0x52, 1 }, //push edx
{ 0x53, 1 }, //push ebx
{ 0x54, 1 }, //push esp
{ 0x55, 1 }, //push ebp
{ 0x56, 1 }, //push esi
{ 0x57, 1 }, //push edi
{ 0x58, 1 }, //pop eax
{ 0x59, 1 }, //pop ecx
{ 0x5a, 1 }, //pop edx
{ 0x5b, 1 }, //pop ebx
{ 0x5c, 1 }, //pop esp
{ 0x5d, 1 }, //pop ebp
{ 0x5e, 1 }, //pop esi
{ 0x5f, 1 }, //pop edi
{ 0x64, 1 }, //fs:
{ 0x65, 1 }, //gs:
{ 0x68, 5 }, //push dword
{ 0x6a, 2 }, //push byte
{ 0x74, 2, RelNear, 0x0f84 }, //je near -> je far
{ 0x75, 2, RelNear, 0x0f85 }, //jne near -> jne far
{ 0x89, 2 }, //mov reg,reg
{ 0x8b, 2 }, //mov reg,reg
{ 0x90, 1 }, //nop
{ 0xa1, 5 }, //mov eax,[dword]
{ 0xeb, 2, RelNear, 0xe9 }, //jmp near -> jmp far
{0x50, 1}, //push eax
{0x51, 1}, //push ecx
{0x52, 1}, //push edx
{0x53, 1}, //push ebx
{0x54, 1}, //push esp
{0x55, 1}, //push ebp
{0x56, 1}, //push esi
{0x57, 1}, //push edi
{0x58, 1}, //pop eax
{0x59, 1}, //pop ecx
{0x5a, 1}, //pop edx
{0x5b, 1}, //pop ebx
{0x5c, 1}, //pop esp
{0x5d, 1}, //pop ebp
{0x5e, 1}, //pop esi
{0x5f, 1}, //pop edi
{0x64, 1}, //fs:
{0x65, 1}, //gs:
{0x68, 5}, //push dword
{0x6a, 2}, //push byte
{0x74, 2, RelNear, 0x0f84}, //je near -> je far
{0x75, 2, RelNear, 0x0f85}, //jne near -> jne far
{0x89, 2}, //mov reg,reg
{0x8b, 2}, //mov reg,reg
{0x90, 1}, //nop
{0xa1, 5}, //mov eax,[dword]
{0xeb, 2, RelNear, 0xe9}, //jmp near -> jmp far
};
bool detour::insert(const string& moduleName, const string& functionName, void*& source, void* target) {
auto detour::insert(const string& moduleName, const string& functionName, void*& source, void* target) -> bool {
HMODULE module = GetModuleHandleW(utf16_t(moduleName));
if(!module) return false;
uint8_t* sourceData = (uint8_t*)GetProcAddress(module, functionName);
uint8* sourceData = (uint8_t*)GetProcAddress(module, functionName);
if(!sourceData) return false;
unsigned sourceLength = detour::length(sourceData);
uint sourceLength = detour::length(sourceData);
if(sourceLength < 5) {
//unable to clone enough bytes to insert hook
#if 1
string output = { "detour::insert(", moduleName, "::", functionName, ") failed: " };
for(unsigned n = 0; n < 16; n++) output.append(hex<2>(sourceData[n]), " ");
string output = {"detour::insert(", moduleName, "::", functionName, ") failed: "};
for(uint n = 0; n < 16; n++) output.append(hex<2>(sourceData[n]), " ");
output.rtrim(" ", 1L);
MessageBoxA(0, output, "nall::detour", MB_OK);
#endif
return false;
}
uint8_t* mirrorData = new uint8_t[512]();
auto mirrorData = new uint8[512]();
detour::mirror(mirrorData, sourceData);
DWORD privileges;
VirtualProtect((void*)mirrorData, 512, PAGE_EXECUTE_READWRITE, &privileges);
VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges);
uintmax_t address = (uintmax_t)target - ((uintmax_t)sourceData + 5);
uintmax address = (uintmax)target - ((uintmax)sourceData + 5);
sourceData[0] = 0xe9; //jmp target
sourceData[1] = address >> 0;
sourceData[2] = address >> 8;
@ -99,22 +99,22 @@ bool detour::insert(const string& moduleName, const string& functionName, void*&
return true;
}
bool detour::remove(const string& moduleName, const string& functionName, void*& source) {
auto detour::remove(const string& moduleName, const string& functionName, void*& source) -> bool {
HMODULE module = GetModuleHandleW(utf16_t(moduleName));
if(!module) return false;
uint8_t* sourceData = (uint8_t*)GetProcAddress(module, functionName);
auto sourceData = (uint8*)GetProcAddress(module, functionName);
if(!sourceData) return false;
uint8_t* mirrorData = (uint8_t*)source;
auto mirrorData = (uint8*)source;
if(mirrorData == sourceData) return false; //hook was never installed
unsigned length = detour::length(256 + mirrorData);
uint length = detour::length(256 + mirrorData);
if(length < 5) return false;
DWORD privileges;
VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges);
for(unsigned n = 0; n < length; n++) sourceData[n] = mirrorData[256 + n];
for(uint n = 0; n < length; n++) sourceData[n] = mirrorData[256 + n];
VirtualProtect((void*)sourceData, 256, privileges, &privileges);
source = (void*)sourceData;
@ -122,8 +122,8 @@ bool detour::remove(const string& moduleName, const string& functionName, void*&
return true;
}
unsigned detour::length(const uint8_t* function) {
unsigned length = 0;
auto detour::length(const uint8* function) -> uint {
uint length = 0;
while(length < 5) {
detour::opcode *opcode = 0;
foreach(op, detour::opcodes) {
@ -138,13 +138,13 @@ unsigned detour::length(const uint8_t* function) {
return length;
}
unsigned detour::mirror(uint8_t* target, const uint8_t* source) {
const uint8_t *entryPoint = source;
for(unsigned n = 0; n < 256; n++) target[256 + n] = source[n];
auto detour::mirror(uint8* target, const uint8* source) -> uint {
const uint8* entryPoint = source;
for(uint n = 0; n < 256; n++) target[256 + n] = source[n];
unsigned size = detour::length(source);
uint size = detour::length(source);
while(size) {
detour::opcode *opcode = 0;
detour::opcode* opcode = nullptr;
foreach(op, detour::opcodes) {
if(*source == op.prefix) {
opcode = &op;
@ -154,15 +154,15 @@ unsigned detour::mirror(uint8_t* target, const uint8_t* source) {
switch(opcode->mode) {
case Copy:
for(unsigned n = 0; n < opcode->length; n++) *target++ = *source++;
for(uint n = 0; n < opcode->length; n++) *target++ = *source++;
break;
case RelNear: {
source++;
uintmax_t sourceAddress = (uintmax_t)source + 1 + (int8_t)*source;
uintmax sourceAddress = (uintmax)source + 1 + (int8)*source;
*target++ = opcode->modify;
if(opcode->modify >> 8) *target++ = opcode->modify >> 8;
uintmax_t targetAddress = (uintmax_t)target + 4;
uintmax_t address = sourceAddress - targetAddress;
uintmax targetAddress = (uintmax)target + 4;
uintmax address = sourceAddress - targetAddress;
*target++ = address >> 0;
*target++ = address >> 8;
*target++ = address >> 16;
@ -174,7 +174,7 @@ unsigned detour::mirror(uint8_t* target, const uint8_t* source) {
size -= opcode->length;
}
uintmax_t address = (entryPoint + detour::length(entryPoint)) - (target + 5);
uintmax address = (entryPoint + detour::length(entryPoint)) - (target + 5);
*target++ = 0xe9; //jmp entryPoint
*target++ = address >> 0;
*target++ = address >> 8;

View File

@ -7,21 +7,21 @@
namespace nall {
//generate unique GUID
inline string guid() {
inline auto guid() -> string {
LinearFeedbackShiftRegisterGenerator lfsr;
lfsr.seed(time(nullptr));
for(unsigned n = 0; n < 256; n++) lfsr();
for(uint n = 0; n < 256; n++) lfsr();
string output;
for(unsigned n = 0; n < 4; n++) output.append(hex(lfsr(), 2L));
for(uint n = 0; n < 4; n++) output.append(hex(lfsr(), 2L));
output.append("-");
for(unsigned n = 0; n < 2; n++) output.append(hex(lfsr(), 2L));
for(uint n = 0; n < 2; n++) output.append(hex(lfsr(), 2L));
output.append("-");
for(unsigned n = 0; n < 2; n++) output.append(hex(lfsr(), 2L));
for(uint n = 0; n < 2; n++) output.append(hex(lfsr(), 2L));
output.append("-");
for(unsigned n = 0; n < 2; n++) output.append(hex(lfsr(), 2L));
for(uint n = 0; n < 2; n++) output.append(hex(lfsr(), 2L));
output.append("-");
for(unsigned n = 0; n < 6; n++) output.append(hex(lfsr(), 2L));
for(uint n = 0; n < 6; n++) output.append(hex(lfsr(), 2L));
return {"{", output, "}"};
}

View File

@ -5,7 +5,7 @@ namespace nall {
//launch a new process and inject specified DLL into it
bool launch(const char* applicationName, const char* libraryName, uint32_t entryPoint) {
auto launch(const char* applicationName, const char* libraryName, uint32 entryPoint) -> bool {
//if a launcher does not send at least one message, a wait cursor will appear
PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0);
MSG msg;
@ -22,19 +22,19 @@ bool launch(const char* applicationName, const char* libraryName, uint32_t entry
);
if(result == false) return false;
uint8_t entryData[1024], entryHook[1024] = {
uint8 entryData[1024], entryHook[1024] = {
0x68, 0x00, 0x00, 0x00, 0x00, //push libraryName
0xb8, 0x00, 0x00, 0x00, 0x00, //mov eax,LoadLibraryW
0xff, 0xd0, //call eax
0xcd, 0x03, //int 3
};
entryHook[1] = (uint8_t)((entryPoint + 14) >> 0);
entryHook[2] = (uint8_t)((entryPoint + 14) >> 8);
entryHook[3] = (uint8_t)((entryPoint + 14) >> 16);
entryHook[4] = (uint8_t)((entryPoint + 14) >> 24);
entryHook[1] = (uint8)((entryPoint + 14) >> 0);
entryHook[2] = (uint8)((entryPoint + 14) >> 8);
entryHook[3] = (uint8)((entryPoint + 14) >> 16);
entryHook[4] = (uint8)((entryPoint + 14) >> 24);
uint32_t pLoadLibraryW = (uint32_t)GetProcAddress(GetModuleHandleW(L"kernel32"), "LoadLibraryW");
auto pLoadLibraryW = (uint32)GetProcAddress(GetModuleHandleW(L"kernel32"), "LoadLibraryW");
entryHook[6] = pLoadLibraryW >> 0;
entryHook[7] = pLoadLibraryW >> 8;
entryHook[8] = pLoadLibraryW >> 16;

View File

@ -24,7 +24,7 @@
namespace nall {
struct registry {
static bool exists(const string& name) {
static auto exists(const string& name) -> bool {
lstring part = name.split("/");
HKEY handle, rootKey = root(part.take(0));
string node = part.take();
@ -39,7 +39,7 @@ struct registry {
return false;
}
static string read(const string& name) {
static auto read(const string& name) -> string {
lstring part = name.split("/");
HKEY handle, rootKey = root(part.take(0));
string node = part.take();
@ -54,12 +54,12 @@ struct registry {
return "";
}
static void write(const string& name, const string& data = "") {
static auto write(const string& name, const string& data = "") -> void {
lstring part = name.split("/");
HKEY handle, rootKey = root(part.take(0));
string node = part.take(), path;
DWORD disposition;
for(unsigned n = 0; n < part.size(); n++) {
for(uint n = 0; n < part.size(); n++) {
path.append(part[n]);
if(RegCreateKeyExW(rootKey, utf16_t(path), 0, nullptr, 0, NWR_FLAGS | KEY_ALL_ACCESS, nullptr, &handle, &disposition) == ERROR_SUCCESS) {
if(n == part.size() - 1) {
@ -71,7 +71,7 @@ struct registry {
}
}
static bool remove(const string& name) {
static auto remove(const string& name) -> bool {
lstring part = name.split("/");
HKEY rootKey = root(part.take(0));
string node = part.take();
@ -80,7 +80,7 @@ struct registry {
return SHDeleteValueW(rootKey, utf16_t(path), utf16_t(node)) == ERROR_SUCCESS;
}
static lstring contents(const string& name) {
static auto contents(const string& name) -> lstring {
lstring part = name.split("/"), result;
HKEY handle, rootKey = root(part.take(0));
part.remove();
@ -88,13 +88,13 @@ struct registry {
if(RegOpenKeyExW(rootKey, utf16_t(path), 0, NWR_FLAGS | KEY_READ, &handle) == ERROR_SUCCESS) {
DWORD folders, nodes;
RegQueryInfoKey(handle, nullptr, nullptr, nullptr, &folders, nullptr, nullptr, &nodes, nullptr, nullptr, nullptr, nullptr);
for(unsigned n = 0; n < folders; n++) {
for(uint n = 0; n < folders; n++) {
wchar_t name[NWR_SIZE] = L"";
DWORD size = NWR_SIZE * sizeof(wchar_t);
RegEnumKeyEx(handle, n, (wchar_t*)&name, &size, nullptr, nullptr, nullptr, nullptr);
result.append(string{(const char*)utf8_t(name), "/"});
}
for(unsigned n = 0; n < nodes; n++) {
for(uint n = 0; n < nodes; n++) {
wchar_t name[NWR_SIZE] = L"";
DWORD size = NWR_SIZE * sizeof(wchar_t);
RegEnumValueW(handle, n, (wchar_t*)&name, &size, nullptr, nullptr, nullptr, nullptr);
@ -106,7 +106,7 @@ struct registry {
}
private:
static HKEY root(const string& name) {
static auto root(const string& name) -> HKEY {
if(name == "HKCR") return HKEY_CLASSES_ROOT;
if(name == "HKCC") return HKEY_CURRENT_CONFIG;
if(name == "HKCU") return HKEY_CURRENT_USER;

View File

@ -14,14 +14,14 @@ struct shared_memory {
explicit operator bool() const { return false; }
auto empty() const -> bool { return true; }
auto size() const -> unsigned { return 0; }
auto size() const -> uint { return 0; }
auto acquired() const -> bool { return false; }
auto acquire() -> uint8_t* { return nullptr; }
auto acquire() -> uint8* { return nullptr; }
auto release() -> void {}
auto reset() -> void {}
auto create(const string& name, unsigned size) -> bool { return false; }
auto create(const string& name, uint size) -> bool { return false; }
auto remove() -> void {}
auto open(const string& name, unsigned size) -> bool { return false; }
auto open(const string& name, uint size) -> bool { return false; }
auto close() -> void {}
};

View File

@ -2,7 +2,7 @@
#define NALL_UTF8_HPP
//UTF-8 <> UTF-16 conversion
//used only for Win32; Linux, etc use UTF-8 internally
//used only for Win32; every other OS uses UTF-8 internally
#if defined(_WIN32)
@ -21,17 +21,9 @@
namespace nall {
//UTF-8 to UTF-16
struct utf16_t {
operator wchar_t*() {
return buffer;
}
operator const wchar_t*() const {
return buffer;
}
utf16_t(const char* s = "") {
if(!s) s = "";
unsigned length = MultiByteToWideChar(CP_UTF8, 0, s, -1, nullptr, 0);
uint length = MultiByteToWideChar(CP_UTF8, 0, s, -1, nullptr, 0);
buffer = new wchar_t[length + 1]();
MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length);
}
@ -40,23 +32,23 @@ namespace nall {
delete[] buffer;
}
operator wchar_t*() {
return buffer;
}
operator const wchar_t*() const {
return buffer;
}
private:
wchar_t* buffer;
wchar_t* buffer = nullptr;
};
//UTF-16 to UTF-8
struct utf8_t {
operator char*() {
return buffer;
}
operator const char*() const {
return buffer;
}
utf8_t(const wchar_t* s = L"") {
if(!s) s = L"";
unsigned length = WideCharToMultiByte(CP_UTF8, 0, s, -1, nullptr, 0, nullptr, nullptr);
uint length = WideCharToMultiByte(CP_UTF8, 0, s, -1, nullptr, 0, nullptr, nullptr);
buffer = new char[length + 1]();
WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, nullptr, nullptr);
}
@ -68,14 +60,22 @@ namespace nall {
utf8_t(const utf8_t&) = delete;
utf8_t& operator=(const utf8_t&) = delete;
operator char*() {
return buffer;
}
operator const char*() const {
return buffer;
}
private:
char* buffer;
char* buffer = nullptr;
};
inline void utf8_args(int& argc, char**& argv) {
inline auto utf8_args(int& argc, char**& argv) -> void {
wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
argv = new char*[argc];
for(unsigned i = 0; i < argc; i++) {
for(uint i = 0; i < argc; i++) {
argv[i] = new char[PATH_MAX];
strcpy(argv[i], nall::utf8_t(wargv[i]));
}

View File

@ -29,15 +29,15 @@ struct Cartridge : property<Cartridge> {
readonly<bool> hasSufamiTurboSlots;
struct Mapping {
function<uint8 (unsigned)> reader;
function<void (unsigned, uint8)> writer;
function<auto (uint, uint8) -> uint8> reader;
function<auto (uint, uint8) -> void> writer;
string addr;
unsigned size = 0;
unsigned base = 0;
unsigned mask = 0;
uint size = 0;
uint base = 0;
uint mask = 0;
Mapping() = default;
Mapping(const function<uint8 (unsigned)>&, const function<void (unsigned, uint8)>&);
Mapping(const function<uint8 (uint, uint8)>&, const function<void (uint, uint8)>&);
Mapping(SuperFamicom::Memory&);
};
vector<Mapping> mapping;

View File

@ -3,7 +3,7 @@ Cartridge::Mapping::Mapping(SuperFamicom::Memory& memory) {
this->writer = {&SuperFamicom::Memory::write, &memory};
}
Cartridge::Mapping::Mapping(const function<uint8 (unsigned)>& reader, const function<void (unsigned, uint8)>& writer) {
Cartridge::Mapping::Mapping(const function<uint8 (uint, uint8)>& reader, const function<void (uint, uint8)>& writer) {
this->reader = reader;
this->writer = writer;
}
@ -217,13 +217,13 @@ auto Cartridge::parseMarkupEvent(Markup::Node root) -> void {
}
if(node["id"].text() == "dr") {
Mapping m([](unsigned) -> uint8 { return cpu.regs.mdr; }, {&Event::dr, &event});
Mapping m([](uint, uint8 data) -> uint8 { return data; }, {&Event::dr, &event});
parseMarkupMap(m, node);
mapping.append(m);
}
if(node["id"].text() == "sr") {
Mapping m({&Event::sr, &event}, [](unsigned, uint8) {});
Mapping m({&Event::sr, &event}, [](uint, uint8) {});
parseMarkupMap(m, node);
mapping.append(m);
}
@ -326,7 +326,7 @@ auto Cartridge::parseMarkupARMDSP(Markup::Node root) -> void {
}
}
auto Cartridge::parseMarkupHitachiDSP(Markup::Node root, unsigned roms) -> void {
auto Cartridge::parseMarkupHitachiDSP(Markup::Node root, uint roms) -> void {
hasHitachiDSP = true;
auto rom = root.find("rom");

View File

@ -52,14 +52,14 @@ auto ArmDSP::enter() -> void {
auto ArmDSP::step(uint clocks) -> void {
if(bridge.timer && --bridge.timer == 0);
Coprocessor::step(clocks);
synchronize_cpu();
synchronizeCPU();
}
//MMIO: $00-3f|80-bf:3800-38ff
//3800-3807 mirrored throughout
//a0 ignored
auto ArmDSP::mmio_read(uint addr) -> uint8 {
auto ArmDSP::mmio_read(uint addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
uint8 data = 0x00;

View File

@ -14,7 +14,7 @@ struct ArmDSP : Processor::ARM, Coprocessor {
auto bus_read(uint mode, uint32 addr) -> uint32 override;
auto bus_write(uint mode, uint32 addr, uint32 word) -> void override;
auto mmio_read(uint addr) -> uint8;
auto mmio_read(uint addr, uint8 data) -> uint8;
auto mmio_write(uint addr, uint8 data) -> void;
auto init() -> void;

View File

@ -1,6 +1,6 @@
struct Coprocessor : Thread {
alwaysinline auto step(uint clocks) -> void;
alwaysinline auto synchronize_cpu() -> void;
alwaysinline auto synchronizeCPU() -> void;
};
#include <sfc/coprocessor/icd2/icd2.hpp>
@ -28,6 +28,6 @@ auto Coprocessor::step(uint clocks) -> void {
clock += clocks * (uint64)cpu.frequency;
}
auto Coprocessor::synchronize_cpu() -> void {
auto Coprocessor::synchronizeCPU() -> void {
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
}

View File

@ -32,7 +32,7 @@ auto EpsonRTC::enter() -> void {
}
step(1);
synchronize_cpu();
synchronizeCPU();
}
}
@ -141,7 +141,7 @@ auto EpsonRTC::sync() -> void {
resync = true; //alert program that time has changed
}
auto EpsonRTC::read(uint addr) -> uint8 {
auto EpsonRTC::read(uint addr, uint8 data) -> uint8 {
cpu.synchronizeCoprocessors();
addr &= 3;
@ -162,6 +162,8 @@ auto EpsonRTC::read(uint addr) -> uint8 {
if(addr == 2) {
return ready << 7;
}
return data;
}
auto EpsonRTC::write(uint addr, uint8 data) -> void {

View File

@ -11,7 +11,7 @@ struct EpsonRTC : Coprocessor {
auto reset() -> void;
auto sync() -> void;
auto read(uint addr) -> uint8;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -28,7 +28,7 @@ auto Event::enter() -> void {
}
step(1);
synchronize_cpu();
synchronizeCPU();
}
}
@ -60,7 +60,7 @@ auto Event::reset() -> void {
scoreSecondsRemaining = 0;
}
auto Event::sr(uint) -> uint8 {
auto Event::sr(uint, uint8) -> uint8 {
return status;
}
@ -72,7 +72,7 @@ auto Event::dr(uint, uint8 data) -> void {
}
}
auto Event::rom_read(uint addr) -> uint8 {
auto Event::rom_read(uint addr, uint8 data) -> uint8 {
if(board == Board::CampusChallenge92) {
uint id = 0;
if(select == 0x09) id = 1;
@ -82,7 +82,7 @@ auto Event::rom_read(uint addr) -> uint8 {
if(addr & 0x008000) {
addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff);
return rom[id].read(bus.mirror(addr, rom[id].size()));
return rom[id].read(bus.mirror(addr, rom[id].size()), data);
}
}
@ -95,21 +95,21 @@ auto Event::rom_read(uint addr) -> uint8 {
if(addr & 0x400000) {
addr &= 0x3fffff;
return rom[id].read(bus.mirror(addr, rom[id].size()));
return rom[id].read(bus.mirror(addr, rom[id].size()), data);
}
if(addr & 0x008000) {
addr &= 0x1fffff;
if(id != 2) addr = ((addr & 0x1f0000) >> 1) | (addr & 0x7fff);
return rom[id].read(bus.mirror(addr, rom[id].size()));
return rom[id].read(bus.mirror(addr, rom[id].size()), data);
}
}
return cpu.regs.mdr;
return data;
}
auto Event::ram_read(uint addr) -> uint8 {
return ram.read(bus.mirror(addr, ram.size()));
auto Event::ram_read(uint addr, uint8 data) -> uint8 {
return ram.read(bus.mirror(addr, ram.size()), data);
}
auto Event::ram_write(uint addr, uint8 data) -> void {

View File

@ -13,10 +13,10 @@ struct Event : Coprocessor {
auto submitScore() -> void;
auto sr(uint) -> uint8;
auto sr(uint, uint8) -> uint8;
auto dr(uint, uint8 data) -> void;
auto rom_read(uint addr) -> uint8;
auto ram_read(uint addr) -> uint8;
auto rom_read(uint addr, uint8) -> uint8;
auto ram_read(uint addr, uint8) -> uint8;
auto ram_write(uint addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -16,7 +16,8 @@ auto HitachiDSP::enter() -> void {
if(mmio.dma) {
for(auto n : range(mmio.dma_length)) {
bus.write(mmio.dma_target + n, bus.read(mmio.dma_source + n));
//todo: access internally, not from Bus
bus.write(mmio.dma_target + n, bus.read(mmio.dma_source + n, 0));
step(2);
}
mmio.dma = false;
@ -25,7 +26,7 @@ auto HitachiDSP::enter() -> void {
exec(mmio.program_offset);
step(1);
synchronize_cpu();
synchronizeCPU();
}
}

View File

@ -18,15 +18,15 @@ struct HitachiDSP : Processor::HG51B, Coprocessor {
auto bus_write(uint24 addr, uint8 data) -> void;
//CPU ROM read/write
auto rom_read(uint addr) -> uint8;
auto rom_read(uint addr, uint8 data) -> uint8;
auto rom_write(uint addr, uint8 data) -> void;
//CPU RAM read/write
auto ram_read(uint addr) -> uint8;
auto ram_read(uint addr, uint8 data) -> uint8;
auto ram_write(uint addr, uint8 data) -> void;
//CPU MMIO read/write
auto dsp_read(uint addr) -> uint8;
auto dsp_read(uint addr, uint8 data) -> uint8;
auto dsp_write(uint addr, uint8 data) -> void;
auto firmware() const -> vector<uint8>;

View File

@ -1,30 +1,32 @@
auto HitachiDSP::bus_read(uint24 addr) -> uint8 {
if((addr & 0x408000) == 0x008000) return bus.read(addr); //$00-3f,80-bf:6000-7fff
if((addr & 0xf88000) == 0x700000) return bus.read(addr); //$70-77:0000-7fff
//todo: read internally, not from Bus
if((addr & 0x408000) == 0x008000) return bus.read(addr, 0); //$00-3f,80-bf:6000-7fff
if((addr & 0xf88000) == 0x700000) return bus.read(addr, 0); //$70-77:0000-7fff
return 0x00;
}
auto HitachiDSP::bus_write(uint24 addr, uint8 data) -> void {
//todo: write internally, not to Bus
if((addr & 0x40e000) == 0x006000) return bus.write(addr, data); //$00-3f,80-bf:6000-7fff
if((addr & 0xf88000) == 0x700000) return bus.write(addr, data); //$70-77:0000-7fff
}
auto HitachiDSP::rom_read(uint addr) -> uint8 {
auto HitachiDSP::rom_read(uint addr, uint8 data) -> uint8 {
if(co_active() == hitachidsp.thread || regs.halt) {
addr = bus.mirror(addr, rom.size());
//if(Roms == 2 && mmio.r1f52 == 1 && addr >= (bit::round(rom.size()) >> 1)) return 0x00;
return rom.read(addr);
return rom.read(addr, data);
}
if((addr & 0x40ffe0) == 0x00ffe0) return mmio.vector[addr & 0x1f];
return cpu.regs.mdr;
return data;
}
auto HitachiDSP::rom_write(uint addr, uint8 data) -> void {
}
auto HitachiDSP::ram_read(uint addr) -> uint8 {
auto HitachiDSP::ram_read(uint addr, uint8 data) -> uint8 {
if(ram.size() == 0) return 0x00; //not open bus
return ram.read(bus.mirror(addr, ram.size()));
return ram.read(bus.mirror(addr, ram.size()), data);
}
auto HitachiDSP::ram_write(uint addr, uint8 data) -> void {
@ -32,7 +34,7 @@ auto HitachiDSP::ram_write(uint addr, uint8 data) -> void {
return ram.write(bus.mirror(addr, ram.size()), data);
}
auto HitachiDSP::dsp_read(uint addr) -> uint8 {
auto HitachiDSP::dsp_read(uint addr, uint8) -> uint8 {
addr &= 0x1fff;
//Data RAM

View File

@ -24,7 +24,7 @@ auto ICD2::enter() -> void {
audio.coprocessor_sample(0x0000, 0x0000);
step(1);
}
synchronize_cpu();
synchronizeCPU();
}
}

View File

@ -8,7 +8,7 @@ struct ICD2 : Emulator::Interface::Bind, GameBoy::Interface::Hook, Coprocessor {
auto power() -> void;
auto reset() -> void;
auto read(uint addr) -> uint8;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -1,5 +1,5 @@
auto ICD2::read(uint addr) -> uint8 {
addr &= 0xffff;
auto ICD2::read(uint addr, uint8 data) -> uint8 {
addr &= 0x40ffff;
//LY counter
if(addr == 0x6000) {
@ -9,7 +9,7 @@ auto ICD2::read(uint addr) -> uint8 {
//command ready port
if(addr == 0x6002) {
bool data = packetsize > 0;
data = packetsize > 0;
if(data) {
for(auto n : range(16)) r7000[n] = packet[0][n];
packetsize--;
@ -24,13 +24,13 @@ auto ICD2::read(uint addr) -> uint8 {
}
//command port
if((addr & 0xfff0) == 0x7000) {
if((addr & 0x40fff0) == 0x7000) {
return r7000[addr & 15];
}
//VRAM port
if(addr == 0x7800) {
uint8 data = output[read_bank * 512 + read_addr];
data = output[read_bank * 512 + read_addr];
read_addr = (read_addr + 1) & 511;
return data;
}

View File

@ -28,13 +28,13 @@ auto MCC::reset() -> void {
}
auto MCC::memory_access(bool write, Memory& memory, uint addr, uint8 data) -> uint8 {
if(write == 0) return memory_read(memory, addr);
if(write == 0) return memory_read(memory, addr, data);
memory_write(memory, addr, data);
}
auto MCC::memory_read(Memory& memory, uint addr) -> uint8 {
auto MCC::memory_read(Memory& memory, uint addr, uint8 data) -> uint8 {
addr = bus.mirror(addr, memory.size());
return memory.read(addr);
return memory.read(addr, data);
}
auto MCC::memory_write(Memory& memory, uint addr, uint8 data) -> void {
@ -86,25 +86,25 @@ auto MCC::mcu_access(bool write, uint addr, uint8 data) -> uint8 {
return memory_access(write, memory, addr & 0x7fffff, data);
}
return cpu.regs.mdr;
return data;
}
auto MCC::mcu_read(uint addr) -> uint8 {
return mcu_access(0, addr);
auto MCC::mcu_read(uint addr, uint8 data) -> uint8 {
return mcu_access(0, addr, data);
}
auto MCC::mcu_write(uint addr, uint8 data) -> void {
mcu_access(1, addr, data);
}
auto MCC::mmio_read(uint addr) -> uint8 {
auto MCC::mmio_read(uint addr, uint8 data) -> uint8 {
if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000
uint8 n = (addr >> 16) & 15;
return r[n];
}
if((addr & 0xf8f000) == 0x105000) { //$10-17:5000-5fff
return memory_read(ram, ((addr >> 16) & 7) * 0x1000 + (addr & 0xfff));
return memory_read(ram, ((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data);
}
return 0x00;

View File

@ -12,14 +12,14 @@ struct MCC {
auto reset() -> void;
auto memory_access(bool write, Memory& memory, uint addr, uint8 data) -> uint8;
auto memory_read(Memory& memory, uint addr) -> uint8;
auto memory_read(Memory& memory, uint addr, uint8 data) -> uint8;
auto memory_write(Memory& memory, uint addr, uint8 data) -> void;
auto mcu_access(bool write, uint addr, uint8 data = 0x00) -> uint8;
auto mcu_read(uint addr) -> uint8;
auto mcu_access(bool write, uint addr, uint8 data) -> uint8;
auto mcu_read(uint addr, uint8 data) -> uint8;
auto mcu_write(uint addr, uint8 data) -> void;
auto mmio_read(uint addr) -> uint8;
auto mmio_read(uint addr, uint8 data) -> uint8;
auto mmio_write(uint addr, uint8 data) -> void;
auto mmio_commit() -> void;

View File

@ -43,7 +43,7 @@ auto MSU1::enter() -> void {
audio.coprocessor_sample(left, right);
step(1);
synchronize_cpu();
synchronizeCPU();
}
}
@ -123,7 +123,7 @@ auto MSU1::audioOpen() -> void {
mmio.audioError = true;
}
auto MSU1::mmioRead(uint addr) -> uint8 {
auto MSU1::mmioRead(uint addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
addr = 0x2000 | (addr & 7);

View File

@ -11,7 +11,7 @@ struct MSU1 : Coprocessor {
auto dataOpen() -> void;
auto audioOpen() -> void;
auto mmioRead(uint addr) -> uint8;
auto mmioRead(uint addr, uint8 data) -> uint8;
auto mmioWrite(uint addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -15,11 +15,11 @@ auto NECDSP::enter() -> void {
exec();
step(1);
synchronize_cpu();
synchronizeCPU();
}
}
auto NECDSP::read(uint addr) -> uint8 {
auto NECDSP::read(uint addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
if(addr & Select) {
return uPD96050::readSR();
@ -37,7 +37,7 @@ auto NECDSP::write(uint addr, uint8 data) -> void {
}
}
auto NECDSP::readRAM(uint addr) -> uint8 {
auto NECDSP::readRAM(uint addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
return uPD96050::readDP(addr);
}

View File

@ -2,10 +2,10 @@ struct NECDSP : Processor::uPD96050, Coprocessor {
static auto Enter() -> void;
auto enter() -> void;
auto read(uint addr) -> uint8;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto readRAM(uint addr) -> uint8;
auto readRAM(uint addr, uint8 data) -> uint8;
auto writeRAM(uint addr, uint8 data) -> void;
auto init() -> void;

View File

@ -23,11 +23,11 @@ auto NSS::set_dip(uint16 dip) -> void {
this->dip = dip;
}
auto NSS::read(uint addr) -> uint8 {
auto NSS::read(uint, uint8) -> uint8 {
return dip;
}
auto NSS::write(uint addr, uint8 data) -> void {
auto NSS::write(uint, uint8) -> void {
}
}

View File

@ -6,7 +6,7 @@ struct NSS {
auto reset() -> void;
auto set_dip(uint16 dip) -> void;
auto read(uint addr) -> uint8;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
uint8 dip = 0x00;

View File

@ -24,7 +24,7 @@ auto OBC1::reset() -> void {
status.shift = (ramRead(0x1ff6) & 3) << 1;
}
auto OBC1::read(uint addr) -> uint8 {
auto OBC1::read(uint addr, uint8) -> uint8 {
addr &= 0x1fff;
switch(addr) {

View File

@ -5,7 +5,7 @@ struct OBC1 {
auto power() -> void;
auto reset() -> void;
auto read(uint addr) -> uint8;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -4,7 +4,7 @@ auto SA1::CPUIRAM::size() const -> uint {
return sa1.iram.size();
}
auto SA1::CPUIRAM::read(uint addr) -> uint8 {
auto SA1::CPUIRAM::read(uint addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
return sa1.iram.read(addr & 0x07ff);
}
@ -18,7 +18,7 @@ auto SA1::CPUBWRAM::size() const -> uint {
return sa1.bwram.size();
}
auto SA1::CPUBWRAM::read(uint addr) -> uint8 {
auto SA1::CPUBWRAM::read(uint addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
if(dma) return sa1.dma_cc1_read(addr);
return sa1.bwram.read(addr);

View File

@ -1,12 +1,12 @@
struct CPUIRAM : Memory {
auto size() const -> uint;
alwaysinline auto read(uint) -> uint8;
alwaysinline auto read(uint, uint8 = 0) -> uint8;
alwaysinline auto write(uint, uint8) -> void;
} cpuiram;
struct CPUBWRAM : Memory {
auto size() const -> uint;
alwaysinline auto read(uint) -> uint8;
alwaysinline auto read(uint, uint8 = 0) -> uint8;
alwaysinline auto write(uint, uint8) -> void;
bool dma;
} cpubwram;

View File

@ -15,13 +15,13 @@ auto SA1::dma_normal() -> void {
switch(mmio.sd) {
case DMA::SourceROM:
if((dsa & 0x408000) == 0x008000 || (dsa & 0xc00000) == 0xc00000) {
data = bus_read(dsa);
data = bus_read(dsa, data);
}
break;
case DMA::SourceBWRAM:
if((dsa & 0x40e000) == 0x006000 || (dsa & 0xf00000) == 0x400000) {
data = bus_read(dsa);
data = bus_read(dsa, data);
}
break;

View File

@ -1,42 +1,42 @@
auto SA1::bus_read(uint addr) -> uint8 {
auto SA1::bus_read(uint addr, uint8 data) -> uint8 {
if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff
return mmio_read(addr);
return mmio_read(addr, data);
}
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
return mmcrom_read(addr);
return mmcrom_read(addr, data);
}
if((addr & 0xc00000) == 0xc00000) { //$c0-ff:0000-ffff
return mmcrom_read(addr);
return mmcrom_read(addr, data);
}
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
return mmc_sa1_read(addr);
return mmc_sa1_read(addr, data);
}
if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
synchronize_cpu();
return iram.read(addr & 2047);
synchronizeCPU();
return iram.read(addr & 2047, data);
}
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
synchronize_cpu();
return iram.read(addr & 2047);
synchronizeCPU();
return iram.read(addr & 2047, data);
}
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
synchronize_cpu();
return bwram.read(addr & (bwram.size() - 1));
synchronizeCPU();
return bwram.read(addr & (bwram.size() - 1), data);
}
if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff
synchronize_cpu();
return bitmap_read(addr & 0x0fffff);
synchronizeCPU();
return bitmap_read(addr & 0x0fffff, data);
}
//unmapped region
return regs.mdr;
return data;
}
auto SA1::bus_write(uint addr, uint8 data) -> void {
@ -49,22 +49,22 @@ auto SA1::bus_write(uint addr, uint8 data) -> void {
}
if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
synchronize_cpu();
synchronizeCPU();
return iram.write(addr & 2047, data);
}
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
synchronize_cpu();
synchronizeCPU();
return iram.write(addr & 2047, data);
}
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
synchronize_cpu();
synchronizeCPU();
return bwram.write(addr & (bwram.size() - 1), data);
}
if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff
synchronize_cpu();
synchronizeCPU();
return bitmap_write(addr & 0x0fffff, data);
}
}
@ -73,29 +73,29 @@ auto SA1::bus_write(uint addr, uint8 data) -> void {
//this is used both to keep VBR-reads from accessing MMIO registers, and
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access
//these ports.
auto SA1::vbr_read(uint addr) -> uint8 {
auto SA1::vbr_read(uint addr, uint8 data) -> uint8 {
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
return mmcrom_read(addr);
return mmcrom_read(addr, data);
}
if((addr & 0xc00000) == 0xc00000) { //$c0-ff:0000-ffff
return mmcrom_read(addr);
return mmcrom_read(addr, data);
}
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
return bwram.read(addr & (bwram.size() - 1));
return bwram.read(addr & (bwram.size() - 1), data);
}
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
return bwram.read(addr & (bwram.size() - 1));
return bwram.read(addr & (bwram.size() - 1), data);
}
if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
return iram.read(addr & 2047);
return iram.read(addr & 2047, data);
}
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
return iram.read(addr & 2047);
return iram.read(addr & 2047, data);
}
return 0x00;
@ -113,7 +113,7 @@ auto SA1::op_io() -> void {
auto SA1::op_read(uint addr) -> uint8 {
tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
return bus_read(addr);
return bus_read(addr, regs.mdr);
}
auto SA1::op_write(uint addr, uint8 data) -> void {
@ -122,7 +122,7 @@ auto SA1::op_write(uint addr, uint8 data) -> void {
bus_write(addr, regs.mdr = data);
}
auto SA1::mmcrom_read(uint addr) -> uint8 {
auto SA1::mmcrom_read(uint addr, uint8) -> uint8 {
if((addr & 0xffffe0) == 0x00ffe0) {
if(addr == 0xffea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0;
if(addr == 0xffeb && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 8;
@ -180,7 +180,7 @@ auto SA1::mmcrom_read(uint addr) -> uint8 {
auto SA1::mmcrom_write(uint addr, uint8 data) -> void {
}
auto SA1::mmcbwram_read(uint addr) -> uint8 {
auto SA1::mmcbwram_read(uint addr, uint8 data) -> uint8 {
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
cpu.synchronizeCoprocessors();
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
@ -191,7 +191,7 @@ auto SA1::mmcbwram_read(uint addr) -> uint8 {
return cpubwram.read(addr & 0x0fffff);
}
return cpu.regs.mdr;
return data;
}
auto SA1::mmcbwram_write(uint addr, uint8 data) -> void {
@ -206,21 +206,21 @@ auto SA1::mmcbwram_write(uint addr, uint8 data) -> void {
}
}
auto SA1::mmc_sa1_read(uint addr) -> uint8 {
synchronize_cpu();
auto SA1::mmc_sa1_read(uint addr, uint8 data) -> uint8 {
synchronizeCPU();
if(mmio.sw46 == 0) {
//$40-43:0000-ffff x 32 projection
addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), bwram.size());
return bwram.read(addr);
return bwram.read(addr, data);
} else {
//$60-6f:0000-ffff x 128 projection
addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), 0x100000);
return bitmap_read(addr);
return bitmap_read(addr, data);
}
}
auto SA1::mmc_sa1_write(uint addr, uint8 data) -> void {
synchronize_cpu();
synchronizeCPU();
if(mmio.sw46 == 0) {
//$40-43:0000-ffff x 32 projection
addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), bwram.size());
@ -232,7 +232,7 @@ auto SA1::mmc_sa1_write(uint addr, uint8 data) -> void {
}
}
auto SA1::bitmap_read(uint addr) -> uint8 {
auto SA1::bitmap_read(uint addr, uint8 data) -> uint8 {
if(mmio.bbf == 0) {
//4bpp
uint shift = addr & 1;

View File

@ -1,19 +1,19 @@
auto bus_read(uint addr) -> uint8;
auto bus_read(uint addr, uint8 data) -> uint8;
auto bus_write(uint addr, uint8 data) -> void;
auto vbr_read(uint addr) -> uint8;
auto vbr_read(uint addr, uint8 data = 0) -> uint8;
alwaysinline auto op_io() -> void;
alwaysinline auto op_read(uint addr) -> uint8;
alwaysinline auto op_write(uint addr, uint8 data) -> void;
auto mmcrom_read(uint addr) -> uint8;
auto mmcrom_read(uint addr, uint8 data) -> uint8;
auto mmcrom_write(uint addr, uint8 data) -> void;
auto mmcbwram_read(uint addr) -> uint8;
auto mmcbwram_read(uint addr, uint8 data) -> uint8;
auto mmcbwram_write(uint addr, uint8 data) -> void;
auto mmc_sa1_read(uint addr) -> uint8;
auto mmc_sa1_read(uint addr, uint8 data) -> uint8;
auto mmc_sa1_write(uint addr, uint8 data) -> void;
auto bitmap_read(uint addr) -> uint8;
auto bitmap_read(uint addr, uint8 data) -> uint8;
auto bitmap_write(uint addr, uint8 data) -> void;

View File

@ -445,8 +445,8 @@ auto SA1::mmio_r230e() -> uint8 {
return 0x01; //true value unknown
}
auto SA1::mmio_read(uint addr) -> uint8 {
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronize_cpu());
auto SA1::mmio_read(uint addr, uint8) -> uint8 {
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronizeCPU());
addr &= 0xffff;
switch(addr) {
@ -471,7 +471,7 @@ auto SA1::mmio_read(uint addr) -> uint8 {
}
auto SA1::mmio_write(uint addr, uint8 data) -> void {
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronize_cpu());
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronizeCPU());
addr &= 0xffff;
switch(addr) {

View File

@ -1,4 +1,4 @@
auto mmio_read(uint addr) -> uint8;
auto mmio_read(uint addr, uint8 data) -> uint8;
auto mmio_write(uint addr, uint8 data) -> void;
struct MMIO {

View File

@ -21,7 +21,7 @@ auto SA1::enter() -> void {
if(mmio.sa1_rdyb || mmio.sa1_resb) {
//SA-1 co-processor is asleep
tick();
synchronize_cpu();
synchronizeCPU();
continue;
}
@ -81,7 +81,7 @@ auto SA1::interrupt_pending() -> bool {
auto SA1::tick() -> void {
step(2);
if(++status.tick_counter == 0) synchronize_cpu();
if(++status.tick_counter == 0) synchronizeCPU();
//adjust counters:
//note that internally, status counters are in clocks;

View File

@ -41,11 +41,11 @@ auto SDD1::reset() -> void {
}
}
auto SDD1::read(uint addr) -> uint8 {
addr &= 0xffff;
auto SDD1::read(uint addr, uint8 data) -> uint8 {
addr &= 0x40ffff;
if((addr & 0x4380) == 0x4300) {
return cpu.mmio_read(addr);
if((addr & 0x404380) == 0x4300) {
return cpu.mmio_read(addr, data);
}
switch(addr) {
@ -55,7 +55,7 @@ auto SDD1::read(uint addr) -> uint8 {
case 0x4807: return mmc[3] >> 20;
}
return cpu.regs.mdr;
return data;
}
auto SDD1::write(uint addr, uint8 data) -> void {
@ -107,7 +107,7 @@ auto SDD1::mmc_read(uint addr) -> uint8 {
//
//the actual S-DD1 transfer can occur on any channel, but it is most likely limited to
//one transfer per $420b write (for spooling purposes). however, this is not known for certain.
auto SDD1::mcurom_read(uint addr) -> uint8 {
auto SDD1::mcurom_read(uint addr, uint8) -> uint8 {
if(addr < 0x400000) { //(addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
return rom.read(addr);
//addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff);
@ -147,16 +147,16 @@ auto SDD1::mcurom_read(uint addr) -> uint8 {
auto SDD1::mcurom_write(uint addr, uint8 data) -> void {
}
auto SDD1::mcuram_read(uint addr) -> uint8 {
auto SDD1::mcuram_read(uint addr, uint8 data) -> uint8 {
if((addr & 0x60e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
return ram.read(addr & 0x1fff);
return ram.read(addr & 0x1fff, data);
}
if((addr & 0xf08000) == 0x700000) { //$70-7f:0000-7fff
return ram.read(addr & 0x1fff);
return ram.read(addr & 0x1fff, data);
}
return cpu.regs.mdr;
return data;
}
auto SDD1::mcuram_write(uint addr, uint8 data) -> void {

View File

@ -5,15 +5,15 @@ struct SDD1 {
auto power() -> void;
auto reset() -> void;
auto read(uint addr) -> uint8;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto mmc_read(uint addr) -> uint8;
auto mcurom_read(uint addr) -> uint8;
auto mcurom_read(uint addr, uint8 data) -> uint8;
auto mcurom_write(uint addr, uint8 data) -> void;
auto mcuram_read(uint addr) -> uint8;
auto mcuram_read(uint addr, uint8 data) -> uint8;
auto mcuram_write(uint addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -7,11 +7,11 @@ namespace SuperFamicom {
#include "serialization.cpp"
SharpRTC sharprtc;
void SharpRTC::Enter() {
auto SharpRTC::Enter() -> void {
sharprtc.enter();
}
void SharpRTC::enter() {
auto SharpRTC::enter() -> void {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
@ -20,14 +20,14 @@ void SharpRTC::enter() {
tick_second();
step(1);
synchronize_cpu();
synchronizeCPU();
}
}
void SharpRTC::init() {
auto SharpRTC::init() -> void {
}
void SharpRTC::load() {
auto SharpRTC::load() -> void {
return;
second = 0;
@ -39,20 +39,20 @@ void SharpRTC::load() {
weekday = 0;
}
void SharpRTC::unload() {
auto SharpRTC::unload() -> void {
}
void SharpRTC::power() {
auto SharpRTC::power() -> void {
}
void SharpRTC::reset() {
auto SharpRTC::reset() -> void {
create(SharpRTC::Enter, 1);
rtc_state = State::Read;
rtc_index = -1;
}
void SharpRTC::sync() {
auto SharpRTC::sync() -> void {
time_t systime = time(0);
tm* timeinfo = localtime(&systime);
@ -65,7 +65,7 @@ void SharpRTC::sync() {
weekday = timeinfo->tm_wday;
}
uint8 SharpRTC::read(unsigned addr) {
auto SharpRTC::read(uint addr, uint8 data) -> uint8 {
addr &= 1;
if(addr == 0) {
@ -82,10 +82,10 @@ uint8 SharpRTC::read(unsigned addr) {
}
}
return cpu.regs.mdr;
return data;
}
void SharpRTC::write(unsigned addr, uint8 data) {
auto SharpRTC::write(uint addr, uint8 data) -> void {
addr &= 1, data &= 15;
if(addr == 1) {

View File

@ -9,7 +9,7 @@ struct SharpRTC : Coprocessor {
auto reset() -> void;
auto sync() -> void;
auto read(uint addr) -> uint8;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -34,7 +34,7 @@ auto SPC7110::enter() -> void {
auto SPC7110::add_clocks(uint clocks) -> void {
step(clocks);
synchronize_cpu();
synchronizeCPU();
}
auto SPC7110::init() -> void {
@ -109,7 +109,7 @@ auto SPC7110::reset() -> void {
r4834 = 0x00;
}
auto SPC7110::read(uint addr) -> uint8 {
auto SPC7110::read(uint addr, uint8 data) -> uint8 {
cpu.synchronizeCoprocessors();
if((addr & 0xff0000) == 0x500000) addr = 0x4800;
addr = 0x4800 | (addr & 0x3f);
@ -145,7 +145,7 @@ auto SPC7110::read(uint addr) -> uint8 {
//==============
case 0x4810: {
uint8 data = r4810;
data = r4810;
data_port_increment_4810();
return data;
}
@ -195,7 +195,7 @@ auto SPC7110::read(uint addr) -> uint8 {
}
return cpu.regs.mdr;
return data;
}
auto SPC7110::write(uint addr, uint8 data) -> void {
@ -264,7 +264,7 @@ auto SPC7110::write(uint addr, uint8 data) -> void {
//SPC7110::MCUROM
//===============
auto SPC7110::mcurom_read(uint addr) -> uint8 {
auto SPC7110::mcurom_read(uint addr, uint8 data) -> uint8 {
uint mask = (1 << (r4834 & 3)) - 1; //8mbit, 16mbit, 32mbit, 64mbit DROM
if((addr & 0x708000) == 0x008000 //$00-0f|80-8f:8000-ffff
@ -305,7 +305,7 @@ auto SPC7110::mcurom_read(uint addr) -> uint8 {
return datarom_read(addr);
}
return cpu.regs.mdr;
return data;
}
auto SPC7110::mcurom_write(uint addr, uint8 data) -> void {
@ -315,7 +315,7 @@ auto SPC7110::mcurom_write(uint addr, uint8 data) -> void {
//SPC7110::MCURAM
//===============
auto SPC7110::mcuram_read(uint addr) -> uint8 {
auto SPC7110::mcuram_read(uint addr, uint8) -> uint8 {
//$00-3f|80-bf:6000-7fff
if(r4830 & 0x80) {
uint bank = (addr >> 16) & 0x3f;

View File

@ -14,13 +14,13 @@ struct SPC7110 : Coprocessor {
auto add_clocks(uint clocks) -> void;
auto read(uint addr) -> uint8;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto mcurom_read(uint addr) -> uint8;
auto mcurom_read(uint addr, uint8 data) -> uint8;
auto mcurom_write(uint addr, uint8 data) -> void;
auto mcuram_read(uint addr) -> uint8;
auto mcuram_read(uint addr, uint8 data) -> uint8;
auto mcuram_write(uint addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -1,33 +1,33 @@
//ROM / RAM access from the S-CPU
auto SuperFX::CPUROM::size() const -> unsigned {
auto SuperFX::CPUROM::size() const -> uint {
return superfx.rom.size();
}
auto SuperFX::CPUROM::read(unsigned addr) -> uint8 {
auto SuperFX::CPUROM::read(uint addr, uint8 data) -> uint8 {
if(superfx.regs.sfr.g && superfx.regs.scmr.ron) {
static const uint8_t data[16] = {
static const uint8 vector[16] = {
0x00, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01,
0x00, 0x01, 0x08, 0x01, 0x00, 0x01, 0x0c, 0x01,
};
return data[addr & 15];
return vector[addr & 15];
}
return superfx.rom.read(addr);
return superfx.rom.read(addr, data);
}
auto SuperFX::CPUROM::write(unsigned addr, uint8 data) -> void {
auto SuperFX::CPUROM::write(uint addr, uint8 data) -> void {
superfx.rom.write(addr, data);
}
auto SuperFX::CPURAM::size() const -> unsigned {
auto SuperFX::CPURAM::size() const -> uint {
return superfx.ram.size();
}
auto SuperFX::CPURAM::read(unsigned addr) -> uint8 {
if(superfx.regs.sfr.g && superfx.regs.scmr.ran) return cpu.regs.mdr;
return superfx.ram.read(addr);
auto SuperFX::CPURAM::read(uint addr, uint8 data) -> uint8 {
if(superfx.regs.sfr.g && superfx.regs.scmr.ran) return data;
return superfx.ram.read(addr, data);
}
auto SuperFX::CPURAM::write(unsigned addr, uint8 data) -> void {
auto SuperFX::CPURAM::write(uint addr, uint8 data) -> void {
superfx.ram.write(addr, data);
}

View File

@ -1,11 +1,11 @@
struct CPUROM : Memory {
auto size() const -> unsigned;
auto read(unsigned) -> uint8;
auto write(unsigned, uint8) -> void;
auto size() const -> uint;
auto read(uint, uint8) -> uint8;
auto write(uint, uint8) -> void;
} cpurom;
struct CPURAM : Memory {
auto size() const -> unsigned;
auto read(unsigned) -> uint8;
auto write(unsigned, uint8) -> void;
auto size() const -> uint;
auto read(uint, uint8) -> uint8;
auto write(uint, uint8) -> void;
} cpuram;

View File

@ -2,7 +2,7 @@ auto SuperFX::bus_read(unsigned addr) -> uint8 {
if((addr & 0xc00000) == 0x000000) { //$00-3f:0000-7fff, $00-3f:8000-ffff
while(!regs.scmr.ron && scheduler.sync != Scheduler::SynchronizeMode::All) {
step(6);
synchronize_cpu();
synchronizeCPU();
}
return rom.read((((addr & 0x3f0000) >> 1) | (addr & 0x7fff)) & rom_mask);
}
@ -10,7 +10,7 @@ auto SuperFX::bus_read(unsigned addr) -> uint8 {
if((addr & 0xe00000) == 0x400000) { //$40-5f:0000-ffff
while(!regs.scmr.ron && scheduler.sync != Scheduler::SynchronizeMode::All) {
step(6);
synchronize_cpu();
synchronizeCPU();
}
return rom.read(addr & rom_mask);
}
@ -18,7 +18,7 @@ auto SuperFX::bus_read(unsigned addr) -> uint8 {
if((addr & 0xe00000) == 0x600000) { //$60-7f:0000-ffff
while(!regs.scmr.ran && scheduler.sync != Scheduler::SynchronizeMode::All) {
step(6);
synchronize_cpu();
synchronizeCPU();
}
return ram.read(addr & ram_mask);
}
@ -28,7 +28,7 @@ auto SuperFX::bus_write(unsigned addr, uint8 data) -> void {
if((addr & 0xe00000) == 0x600000) { //$60-7f:0000-ffff
while(!regs.scmr.ran && scheduler.sync != Scheduler::SynchronizeMode::All) {
step(6);
synchronize_cpu();
synchronizeCPU();
}
return ram.write(addr & ram_mask, data);
}

View File

@ -1,4 +1,4 @@
auto SuperFX::mmio_read(unsigned addr) -> uint8 {
auto SuperFX::mmio_read(uint addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
addr &= 0xffff;
@ -50,7 +50,7 @@ auto SuperFX::mmio_read(unsigned addr) -> uint8 {
return 0x00;
}
auto SuperFX::mmio_write(unsigned addr, uint8 data) -> void {
auto SuperFX::mmio_write(uint addr, uint8 data) -> void {
cpu.synchronizeCoprocessors();
addr &= 0xffff;
@ -59,7 +59,7 @@ auto SuperFX::mmio_write(unsigned addr, uint8 data) -> void {
}
if(addr >= 0x3000 && addr <= 0x301f) {
unsigned n = (addr >> 1) & 15;
uint n = (addr >> 1) & 15;
if((addr & 1) == 0) {
regs.r[n] = (regs.r[n] & 0xff00) | data;
} else {

View File

@ -1,2 +1,2 @@
auto mmio_read(unsigned addr) -> uint8;
auto mmio_write(unsigned addr, uint8 data) -> void;
auto mmio_read(uint addr, uint8 data) -> uint8;
auto mmio_write(uint addr, uint8 data) -> void;

View File

@ -15,7 +15,7 @@ auto SuperFX::step(unsigned clocks) -> void {
}
Coprocessor::step(clocks);
synchronize_cpu();
synchronizeCPU();
}
auto SuperFX::rombuffer_sync() -> void {

View File

@ -78,8 +78,8 @@ auto CPU::enter() -> void {
} else if(status.reset_pending) {
status.reset_pending = false;
add_clocks(186);
regs.pc.l = bus.read(0xfffc);
regs.pc.h = bus.read(0xfffd);
regs.pc.l = bus.read(0xfffc, regs.mdr);
regs.pc.h = bus.read(0xfffd, regs.mdr);
}
}
@ -93,8 +93,8 @@ auto CPU::op_step() -> void {
}
auto CPU::enable() -> void {
function<uint8 (unsigned)> reader{&CPU::mmio_read, (CPU*)&cpu};
function<void (unsigned, uint8)> writer{&CPU::mmio_write, (CPU*)&cpu};
function<auto (uint, uint8) -> uint8> reader{&CPU::mmio_read, (CPU*)&cpu};
function<auto (uint, uint8) -> void> writer{&CPU::mmio_write, (CPU*)&cpu};
bus.map(reader, writer, 0x00, 0x3f, 0x2140, 0x2183);
bus.map(reader, writer, 0x80, 0xbf, 0x2140, 0x2183);
@ -108,8 +108,8 @@ auto CPU::enable() -> void {
bus.map(reader, writer, 0x00, 0x3f, 0x4300, 0x437f);
bus.map(reader, writer, 0x80, 0xbf, 0x4300, 0x437f);
reader = [](unsigned addr) { return cpu.wram[addr]; };
writer = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; };
reader = [](uint addr, uint8) -> uint8 { return cpu.wram[addr]; };
writer = [](uint addr, uint8 data) -> void { cpu.wram[addr] = data; };
bus.map(reader, writer, 0x00, 0x3f, 0x0000, 0x1fff, 0x002000);
bus.map(reader, writer, 0x80, 0xbf, 0x0000, 0x1fff, 0x002000);

View File

@ -24,7 +24,7 @@ auto CPU::dma_addr_valid(uint32 abus) -> bool {
auto CPU::dma_read(uint32 abus) -> uint8 {
if(dma_addr_valid(abus) == false) return 0x00;
return bus.read(abus);
return bus.read(abus, regs.mdr);
}
//simulate two-stage pipeline for DMA transfers; example:
@ -47,7 +47,7 @@ auto CPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) -> void {
dma_write(dma_transfer_valid(bbus, abus), 0x2100 | bbus, regs.mdr);
} else {
dma_add_clocks(4);
regs.mdr = dma_transfer_valid(bbus, abus) ? bus.read(0x2100 | bbus) : 0x00;
regs.mdr = dma_transfer_valid(bbus, abus) ? bus.read(0x2100 | bbus, regs.mdr) : 0x00;
dma_add_clocks(4);
dma_write(dma_addr_valid(abus), abus, regs.mdr);
}

View File

@ -17,7 +17,7 @@ auto CPU::op_read(uint32 addr) -> uint8 {
status.clock_count = speed(addr);
dma_edge();
add_clocks(status.clock_count - 4);
regs.mdr = bus.read(addr);
regs.mdr = bus.read(addr, regs.mdr);
add_clocks(4);
alu_edge();
debugger.op_read(addr, regs.mdr);
@ -44,5 +44,5 @@ auto CPU::speed(uint addr) const -> uint {
}
auto CPU::disassembler_read(uint32 addr) -> uint8 {
return bus.read(addr);
return bus.read(addr, regs.mdr);
}

View File

@ -8,7 +8,7 @@ auto CPU::joylatch() -> bool {
//WMDATA
auto CPU::mmio_r2180() -> uint8 {
return bus.read(0x7e0000 | status.wram_addr++);
return bus.read(0x7e0000 | status.wram_addr++, regs.mdr);
}
//WMDATA
@ -405,7 +405,7 @@ auto CPU::mmio_reset() -> void {
alu.shift = 0;
}
auto CPU::mmio_read(uint addr) -> uint8 {
auto CPU::mmio_read(uint addr, uint8 data) -> uint8 {
addr &= 0xffff;
//APU
@ -416,7 +416,7 @@ auto CPU::mmio_read(uint addr) -> uint8 {
//DMA
if((addr & 0xff80) == 0x4300) { //$4300-$437f
unsigned i = (addr >> 4) & 7;
uint i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0: return mmio_r43x0(i);
case 0x1: return mmio_r43x1(i);
@ -459,7 +459,7 @@ auto CPU::mmio_read(uint addr) -> uint8 {
case 0x421f: return mmio_r421f();
}
return regs.mdr;
return data;
}
auto CPU::mmio_write(uint addr, uint8 data) -> void {
@ -474,7 +474,7 @@ auto CPU::mmio_write(uint addr, uint8 data) -> void {
//DMA
if((addr & 0xff80) == 0x4300) { //$4300-$437f
unsigned i = (addr >> 4) & 7;
uint i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0: mmio_w43x0(i, data); return;
case 0x1: mmio_w43x1(i, data); return;

View File

@ -1,5 +1,5 @@
public:
auto mmio_read(uint addr) -> uint8;
auto mmio_read(uint addr, uint8 data) -> uint8;
auto mmio_write(uint addr, uint8 data) -> void;
privileged:

View File

@ -8,8 +8,8 @@ auto eBoot::init() -> void {
}
auto eBoot::load() -> void {
resetVector = bus.read(0xfffc) << 0;
resetVector |= bus.read(0xfffd) << 8;
resetVector = bus.read(0xfffc, 0x00) << 0;
resetVector |= bus.read(0xfffd, 0x00) << 8;
for(auto& byte : ram) byte = 0xdb;
ram[0] = 0x6c; //jmp ($fffc)
@ -35,12 +35,12 @@ auto eBoot::reset() -> void {
booted = false;
}
auto eBoot::read(uint addr) -> uint8 {
addr &= 0xffff;
auto eBoot::read(uint addr, uint8 data) -> uint8 {
addr &= 0x40ffff;
if(addr == 0xfffc) return booted ? resetVector >> 0 : 0x84;
if(addr == 0xfffd) return booted ? resetVector >> 8 : (booted = true, 0x21);
if(addr >= 0x2184 && addr <= 0x21ff) return ram[addr - 0x2184];
return 0xdb; //should never occur
return data;
}
auto eBoot::write(uint addr, uint8 data) -> void {

View File

@ -5,7 +5,7 @@ struct eBoot : Memory {
auto power() -> void;
auto reset() -> void;
auto read(uint addr) -> uint8;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
private:

View File

@ -22,7 +22,7 @@ auto Satellaview::reset() -> void {
memory::fill(&regs, sizeof regs);
}
auto Satellaview::read(uint addr) -> uint8 {
auto Satellaview::read(uint addr, uint8 data) -> uint8 {
addr &= 0xffff;
switch(addr) {
@ -77,7 +77,7 @@ auto Satellaview::read(uint addr) -> uint8 {
case 0x2199: return regs.r2199;
}
return cpu.regs.mdr;
return data;
}
auto Satellaview::write(uint addr, uint8 data) -> void {

View File

@ -5,7 +5,7 @@ struct Satellaview : Memory {
auto power() -> void;
auto reset() -> void;
auto read(uint addr) -> uint8;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
private:

View File

@ -1,19 +1,19 @@
//Memory
auto Memory::size() const -> unsigned { return 0; }
auto Memory::size() const -> uint { return 0; }
//StaticRAM
StaticRAM::StaticRAM(unsigned n) : size_(n) { data_ = new uint8[size_]; }
StaticRAM::StaticRAM(uint n) : size_(n) { data_ = new uint8[size_]; }
StaticRAM::~StaticRAM() { delete[] data_; }
auto StaticRAM::data() -> uint8* { return data_; }
auto StaticRAM::size() const -> unsigned { return size_; }
auto StaticRAM::size() const -> uint { return size_; }
auto StaticRAM::read(unsigned addr) -> uint8 { return data_[addr]; }
auto StaticRAM::write(unsigned addr, uint8 n) -> void { data_[addr] = n; }
auto StaticRAM::operator[](unsigned addr) -> uint8& { return data_[addr]; }
auto StaticRAM::operator[](unsigned addr) const -> const uint8& { return data_[addr]; }
auto StaticRAM::read(uint addr, uint8) -> uint8 { return data_[addr]; }
auto StaticRAM::write(uint addr, uint8 data) -> void { data_[addr] = data; }
auto StaticRAM::operator[](uint addr) -> uint8& { return data_[addr]; }
auto StaticRAM::operator[](uint addr) const -> const uint8& { return data_[addr]; }
//MappedRAM
@ -26,7 +26,7 @@ auto MappedRAM::reset() -> void {
write_protect_ = false;
}
auto MappedRAM::map(uint8* source, unsigned length) -> void {
auto MappedRAM::map(uint8* source, uint length) -> void {
reset();
data_ = source;
size_ = data_ ? length : 0;
@ -46,18 +46,18 @@ auto MappedRAM::read(const stream& memory) -> void {
auto MappedRAM::write_protect(bool status) -> void { write_protect_ = status; }
auto MappedRAM::data() -> uint8* { return data_; }
auto MappedRAM::size() const -> unsigned { return size_; }
auto MappedRAM::size() const -> uint { return size_; }
auto MappedRAM::read(unsigned addr) -> uint8 { return data_[addr]; }
auto MappedRAM::write(unsigned addr, uint8 n) -> void { if(!write_protect_) data_[addr] = n; }
auto MappedRAM::operator[](unsigned addr) const -> const uint8& { return data_[addr]; }
auto MappedRAM::read(uint addr, uint8) -> uint8 { return data_[addr]; }
auto MappedRAM::write(uint addr, uint8 data) -> void { if(!write_protect_) data_[addr] = data; }
auto MappedRAM::operator[](uint addr) const -> const uint8& { return data_[addr]; }
//Bus
auto Bus::mirror(unsigned addr, unsigned size) -> unsigned {
auto Bus::mirror(uint addr, uint size) -> uint {
if(size == 0) return 0;
unsigned base = 0;
unsigned mask = 1 << 23;
uint base = 0;
uint mask = 1 << 23;
while(addr >= size) {
while(!(addr & mask)) mask >>= 1;
addr -= mask;
@ -70,17 +70,17 @@ auto Bus::mirror(unsigned addr, unsigned size) -> unsigned {
return base + addr;
}
auto Bus::reduce(unsigned addr, unsigned mask) -> unsigned {
auto Bus::reduce(uint addr, uint mask) -> uint {
while(mask) {
unsigned bits = (mask & -mask) - 1;
uint bits = (mask & -mask) - 1;
addr = ((addr >> 1) & ~bits) | (addr & bits);
mask = (mask & (mask - 1)) >> 1;
}
return addr;
}
auto Bus::read(unsigned addr) -> uint8 {
uint8 data = reader[lookup[addr]](target[addr]);
auto Bus::read(uint addr, uint8 data) -> uint8 {
data = reader[lookup[addr]](target[addr], data);
if(cheat.enable()) {
if(auto result = cheat.find(addr, data)) return result();
@ -89,6 +89,6 @@ auto Bus::read(unsigned addr) -> uint8 {
return data;
}
auto Bus::write(unsigned addr, uint8 data) -> void {
auto Bus::write(uint addr, uint8 data) -> void {
return writer[lookup[addr]](target[addr], data);
}

View File

@ -15,8 +15,8 @@ Bus::~Bus() {
}
auto Bus::reset() -> void {
function<uint8 (unsigned)> reader = [](unsigned) { return cpu.regs.mdr; };
function<void (unsigned, uint8)> writer = [](unsigned, uint8) {};
function<auto (uint, uint8) -> uint8> reader = [](uint, uint8 data) { return data; };
function<auto (uint, uint8) -> void> writer = [](uint, uint8) {};
idcount = 0;
map(reader, writer, 0x00, 0xff, 0x0000, 0xffff);
@ -31,10 +31,10 @@ auto Bus::map() -> void {
for(auto& addr : addrs) {
lstring bankpart = bank.split("-", 1L);
lstring addrpart = addr.split("-", 1L);
unsigned banklo = hex(bankpart(0));
unsigned bankhi = hex(bankpart(1, bankpart(0)));
unsigned addrlo = hex(addrpart(0));
unsigned addrhi = hex(addrpart(1, addrpart(0)));
uint banklo = hex(bankpart(0));
uint bankhi = hex(bankpart(1, bankpart(0)));
uint addrlo = hex(addrpart(0));
uint addrhi = hex(addrpart(1, addrpart(0)));
map(m.reader, m.writer, banklo, bankhi, addrlo, addrhi, m.size, m.base, m.mask);
}
}
@ -42,23 +42,22 @@ auto Bus::map() -> void {
}
auto Bus::map(
const function<uint8 (unsigned)>& reader,
const function<void (unsigned, uint8)>& writer,
unsigned banklo, unsigned bankhi,
unsigned addrlo, unsigned addrhi,
unsigned size, unsigned base, unsigned mask
const function<uint8 (uint, uint8)>& reader,
const function<void (uint, uint8)>& writer,
uint banklo, uint bankhi, uint addrlo, uint addrhi,
uint size, uint base, uint mask
) -> void {
assert(banklo <= bankhi && banklo <= 0xff);
assert(addrlo <= addrhi && addrlo <= 0xffff);
assert(banklo <= bankhi && bankhi <= 0xff);
assert(addrlo <= addrhi && addrhi <= 0xffff);
assert(idcount < 255);
unsigned id = idcount++;
uint id = idcount++;
this->reader[id] = reader;
this->writer[id] = writer;
for(unsigned bank = banklo; bank <= bankhi; bank++) {
for(unsigned addr = addrlo; addr <= addrhi; addr++) {
unsigned offset = reduce(bank << 16 | addr, mask);
for(uint bank = banklo; bank <= bankhi; bank++) {
for(uint addr = addrlo; addr <= addrhi; addr++) {
uint offset = reduce(bank << 16 | addr, mask);
if(size) offset = base + mirror(offset, size - base);
lookup[bank << 16 | addr] = id;
target[bank << 16 | addr] = offset;

View File

@ -1,72 +1,71 @@
struct Memory {
virtual inline auto size() const -> unsigned;
virtual auto read(unsigned addr) -> uint8 = 0;
virtual auto write(unsigned addr, uint8 data) -> void = 0;
virtual inline auto size() const -> uint;
virtual auto read(uint addr, uint8 data = 0) -> uint8 = 0;
virtual auto write(uint addr, uint8 data) -> void = 0;
};
struct StaticRAM : Memory {
inline StaticRAM(unsigned size);
inline StaticRAM(uint size);
inline ~StaticRAM();
inline auto data() -> uint8*;
inline auto size() const -> unsigned;
inline auto size() const -> uint;
inline auto read(unsigned addr) -> uint8;
inline auto write(unsigned addr, uint8 n) -> void;
inline auto operator[](unsigned addr) -> uint8&;
inline auto operator[](unsigned addr) const -> const uint8&;
inline auto read(uint addr, uint8 data = 0) -> uint8;
inline auto write(uint addr, uint8 data) -> void;
inline auto operator[](uint addr) -> uint8&;
inline auto operator[](uint addr) const -> const uint8&;
private:
uint8* data_ = nullptr;
unsigned size_ = 0;
uint size_ = 0;
};
struct MappedRAM : Memory {
inline auto reset() -> void;
inline auto map(uint8*, unsigned) -> void;
inline auto map(uint8*, uint) -> void;
inline auto copy(const stream& memory) -> void;
inline auto read(const stream& memory) -> void;
inline auto write_protect(bool status) -> void;
inline auto data() -> uint8*;
inline auto size() const -> unsigned;
inline auto size() const -> uint;
inline auto read(unsigned addr) -> uint8;
inline auto write(unsigned addr, uint8 n) -> void;
inline auto operator[](unsigned addr) const -> const uint8&;
inline auto read(uint addr, uint8 data = 0) -> uint8;
inline auto write(uint addr, uint8 data) -> void;
inline auto operator[](uint addr) const -> const uint8&;
private:
uint8* data_ = nullptr;
unsigned size_ = 0;
uint size_ = 0;
bool write_protect_ = false;
};
struct Bus {
alwaysinline static auto mirror(unsigned addr, unsigned size) -> unsigned;
alwaysinline static auto reduce(unsigned addr, unsigned mask) -> unsigned;
alwaysinline static auto mirror(uint addr, uint size) -> uint;
alwaysinline static auto reduce(uint addr, uint mask) -> uint;
Bus();
~Bus();
alwaysinline auto read(unsigned addr) -> uint8;
alwaysinline auto write(unsigned addr, uint8 data) -> void;
alwaysinline auto read(uint addr, uint8 data) -> uint8;
alwaysinline auto write(uint addr, uint8 data) -> void;
auto reset() -> void;
auto map() -> void;
auto map(
const function<uint8 (unsigned)>& reader,
const function<void (unsigned, uint8)>& writer,
unsigned banklo, unsigned bankhi,
unsigned addrlo, unsigned addrhi,
unsigned size = 0, unsigned base = 0, unsigned mask = 0
const function<uint8 (uint, uint8)>& reader,
const function<void (uint, uint8)>& writer,
uint banklo, uint bankhi, uint addrlo, uint addrhi,
uint size = 0, uint base = 0, uint mask = 0
) -> void;
uint8* lookup = nullptr;
uint32* target = nullptr;
unsigned idcount = 0;
function<uint8 (unsigned)> reader[256];
function<void (unsigned, uint8)> writer[256];
uint idcount = 0;
function<auto (uint, uint8) -> uint8> reader[256];
function<auto (uint, uint8) -> void> writer[256];
};
extern Bus bus;

View File

@ -788,7 +788,7 @@ auto PPU::mmio_reset() -> void {
regs.vcounter = 0;
}
auto PPU::mmio_read(uint addr) -> uint8 {
auto PPU::mmio_read(uint addr, uint8 data) -> uint8 {
cpu.synchronizePPU();
switch(addr & 0xffff) {
@ -824,7 +824,7 @@ auto PPU::mmio_read(uint addr) -> uint8 {
case 0x213f: return mmio_r213f(); //STAT78
}
return cpu.regs.mdr;
return data;
}
auto PPU::mmio_write(uint addr, uint8 data) -> void {

View File

@ -1,5 +1,5 @@
public:
auto mmio_read(uint addr) -> uint8;
auto mmio_read(uint addr, uint8 data) -> uint8;
auto mmio_write(uint addr, uint8 data) -> void;
privileged:

View File

@ -94,8 +94,8 @@ auto PPU::add_clocks(uint clocks) -> void {
}
auto PPU::enable() -> void {
function<uint8 (unsigned)> reader{&PPU::mmio_read, (PPU*)&ppu};
function<void (unsigned, uint8)> writer{&PPU::mmio_write, (PPU*)&ppu};
function<auto (uint, uint8) -> uint8> reader{&PPU::mmio_read, (PPU*)&ppu};
function<auto (uint, uint8) -> void> writer{&PPU::mmio_write, (PPU*)&ppu};
bus.map(reader, writer, 0x00, 0x3f, 0x2100, 0x213f);
bus.map(reader, writer, 0x80, 0xbf, 0x2100, 0x213f);

View File

@ -31,12 +31,12 @@ auto SatellaviewCartridge::reset() -> void {
memory.write_protect(!regs.write_enable);
}
auto SatellaviewCartridge::size() const -> unsigned {
auto SatellaviewCartridge::size() const -> uint {
return memory.size();
}
auto SatellaviewCartridge::read(unsigned addr) -> uint8 {
if(readonly) return memory.read(bus.mirror(addr, memory.size()));
auto SatellaviewCartridge::read(uint addr, uint8 data) -> uint8 {
if(readonly) return memory.read(bus.mirror(addr, memory.size()), data);
if(addr == 0x0002) {
if(regs.flash_enable) return 0x80;
@ -61,10 +61,10 @@ auto SatellaviewCartridge::read(unsigned addr) -> uint8 {
}
}
return memory.read(addr);
return memory.read(addr, data);
}
auto SatellaviewCartridge::write(unsigned addr, uint8 data) -> void {
auto SatellaviewCartridge::write(uint addr, uint8 data) -> void {
if(readonly) return;
if((addr & 0xff0000) == 0) {

View File

@ -5,16 +5,16 @@ struct SatellaviewCartridge : Memory {
auto power() -> void;
auto reset() -> void;
auto size() const -> unsigned;
auto read(unsigned addr) -> uint8;
auto write(unsigned addr, uint8 data) -> void;
auto size() const -> uint;
auto read(uint addr, uint8) -> uint8;
auto write(uint addr, uint8 data) -> void;
MappedRAM memory;
bool readonly;
private:
struct {
unsigned command;
uint command;
uint8 write_old;
uint8 write_new;