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 { namespace Emulator {
static const string Name = "higan"; 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 Author = "byuu";
static const string License = "GPLv3"; static const string License = "GPLv3";
static const string Website = "http://byuu.org/"; static const string Website = "http://byuu.org/";

View File

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

View File

@ -119,7 +119,13 @@ auto pListView::setBordered(bool bordered) -> void {
} }
auto pListView::setFocused() -> 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); gtk_widget_grab_focus(gtkWidgetChild);
if(!selected) gtk_tree_selection_unselect_all(gtkTreeSelection);
unlock();
} }
auto pListView::setFont(const Font& font) -> void { 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); 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 pTreeView::setForegroundColor(Color color) -> void {
auto gdkColor = CreateColor(color); auto gdkColor = CreateColor(color);
gtk_widget_modify_text(gtkWidgetChild, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); 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 append(sTreeViewItem item) -> void;
auto remove(sTreeViewItem item) -> void; auto remove(sTreeViewItem item) -> void;
auto setBackgroundColor(Color color) -> void; auto setBackgroundColor(Color color) -> void;
auto setFocused() -> void override;
auto setForegroundColor(Color color) -> void; auto setForegroundColor(Color color) -> void;
auto _activatePath(GtkTreePath* gtkPath) -> void; auto _activatePath(GtkTreePath* gtkPath) -> void;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@ namespace nall {
template<typename T> struct function; 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 //value = true if auto L::operator()(P...) -> R exists
template<typename L> struct is_compatible { 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; 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 { namespace mosaic {
struct bitstream { struct bitstream {
filemap fp; ~bitstream() {
uint8_t* data = nullptr; close();
unsigned size = 0; }
bool readonly = false;
bool endian = 1;
bool read(uint64_t addr) const { auto read(uint64 addr) const -> bool {
if(data == nullptr || (addr >> 3) >= size) return 0; 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; 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; 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 == 0) data[addr >> 3] &= ~mask;
if(value == 1) data[addr >> 3] |= mask; if(value == 1) data[addr >> 3] |= mask;
} }
bool open(const string& filename) { auto open(const string& filename) -> bool {
readonly = false; readonly = false;
if(fp.open(filename, filemap::mode::readwrite) == false) { if(fp.open(filename, filemap::mode::readwrite) == false) {
readonly = true; readonly = true;
@ -36,17 +34,16 @@ struct bitstream {
return true; return true;
} }
void close() { auto close() -> void {
fp.close(); fp.close();
data = nullptr; data = nullptr;
} }
bitstream() { filemap fp;
} uint8* data = nullptr;
uint size = 0;
~bitstream() { bool readonly = false;
close(); bool endian = 1;
}
}; };
} }

View File

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

View File

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

View File

@ -5,17 +5,17 @@ namespace nall {
#define autostream(...) (*makestream(__VA_ARGS__)) #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(".gz")) return std::unique_ptr<stream>(new gzipstream(filestream{path}));
if(path.iendsWith(".zip")) return std::unique_ptr<stream>(new zipstream(filestream{path})); if(path.iendsWith(".zip")) return std::unique_ptr<stream>(new zipstream(filestream{path}));
return std::unique_ptr<stream>(new mmapstream(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)); 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)); return std::unique_ptr<stream>(new memorystream(data, size));
} }

View File

@ -9,18 +9,6 @@ struct filestream : stream {
using stream::read; using stream::read;
using stream::write; 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) { filestream(const string& filename) {
pfile.open(filename, file::mode::readwrite); pfile.open(filename, file::mode::readwrite);
pwritable = pfile.open(); pwritable = pfile.open();
@ -32,6 +20,18 @@ struct filestream : stream {
pwritable = mode == file::mode::write || mode == file::mode::readwrite; 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: private:
mutable file pfile; mutable file pfile;
bool pwritable; bool pwritable;

View File

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

View File

@ -9,37 +9,41 @@ struct memorystream : stream {
using stream::read; using stream::read;
using stream::write; using stream::write;
bool seekable() const { return true; } memorystream() = default;
bool readable() const { return true; }
bool writable() const { return pwritable; }
bool randomaccess() const { return true; }
uint8_t* data() const { return pdata; } memorystream(uint8* data, uint size) {
unsigned size() const { return psize; } pdata = data;
unsigned offset() const { return poffset; } psize = size;
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;
pwritable = true; pwritable = true;
} }
memorystream(const uint8_t* data, unsigned size) { memorystream(const uint8* data, uint size) {
pdata = (uint8_t*)data, psize = size, poffset = 0; pdata = (uint8*)data;
psize = size;
pwritable = false; 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: protected:
mutable uint8_t* pdata; mutable uint8* pdata = nullptr;
mutable unsigned psize, poffset, pwritable; 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::read;
using stream::write; 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) { mmapstream(const string& filename) {
pmmap.open(filename, filemap::mode::readwrite); pmmap.open(filename, filemap::mode::readwrite);
pwritable = pmmap.open(); pwritable = pmmap.open();
if(!pwritable) pmmap.open(filename, filemap::mode::read); 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: private:
mutable filemap pmmap; mutable filemap pmmap;
mutable uint8_t* pdata; mutable uint8* pdata = nullptr;
mutable unsigned pwritable, poffset; mutable uint poffset = 0;
mutable bool pwritable = false;
}; };
} }

View File

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

View File

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

View File

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

View File

@ -7,21 +7,21 @@
namespace nall { namespace nall {
//generate unique GUID //generate unique GUID
inline string guid() { inline auto guid() -> string {
LinearFeedbackShiftRegisterGenerator lfsr; LinearFeedbackShiftRegisterGenerator lfsr;
lfsr.seed(time(nullptr)); lfsr.seed(time(nullptr));
for(unsigned n = 0; n < 256; n++) lfsr(); for(uint n = 0; n < 256; n++) lfsr();
string output; 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("-"); 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("-"); 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("-"); 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("-"); 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, "}"}; return {"{", output, "}"};
} }

View File

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

View File

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

View File

@ -14,14 +14,14 @@ struct shared_memory {
explicit operator bool() const { return false; } explicit operator bool() const { return false; }
auto empty() const -> bool { return true; } 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 acquired() const -> bool { return false; }
auto acquire() -> uint8_t* { return nullptr; } auto acquire() -> uint8* { return nullptr; }
auto release() -> void {} auto release() -> void {}
auto reset() -> 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 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 {} auto close() -> void {}
}; };

View File

@ -2,7 +2,7 @@
#define NALL_UTF8_HPP #define NALL_UTF8_HPP
//UTF-8 <> UTF-16 conversion //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) #if defined(_WIN32)
@ -21,17 +21,9 @@
namespace nall { namespace nall {
//UTF-8 to UTF-16 //UTF-8 to UTF-16
struct utf16_t { struct utf16_t {
operator wchar_t*() {
return buffer;
}
operator const wchar_t*() const {
return buffer;
}
utf16_t(const char* s = "") { utf16_t(const char* s = "") {
if(!s) 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](); buffer = new wchar_t[length + 1]();
MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length); MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length);
} }
@ -40,23 +32,23 @@ namespace nall {
delete[] buffer; delete[] buffer;
} }
operator wchar_t*() {
return buffer;
}
operator const wchar_t*() const {
return buffer;
}
private: private:
wchar_t* buffer; wchar_t* buffer = nullptr;
}; };
//UTF-16 to UTF-8 //UTF-16 to UTF-8
struct utf8_t { struct utf8_t {
operator char*() {
return buffer;
}
operator const char*() const {
return buffer;
}
utf8_t(const wchar_t* s = L"") { utf8_t(const wchar_t* s = L"") {
if(!s) 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](); buffer = new char[length + 1]();
WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, nullptr, nullptr); WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, nullptr, nullptr);
} }
@ -68,14 +60,22 @@ namespace nall {
utf8_t(const utf8_t&) = delete; utf8_t(const utf8_t&) = delete;
utf8_t& operator=(const utf8_t&) = delete; utf8_t& operator=(const utf8_t&) = delete;
operator char*() {
return buffer;
}
operator const char*() const {
return buffer;
}
private: 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); wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
argv = new char*[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]; argv[i] = new char[PATH_MAX];
strcpy(argv[i], nall::utf8_t(wargv[i])); strcpy(argv[i], nall::utf8_t(wargv[i]));
} }

View File

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

View File

@ -3,7 +3,7 @@ Cartridge::Mapping::Mapping(SuperFamicom::Memory& memory) {
this->writer = {&SuperFamicom::Memory::write, &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->reader = reader;
this->writer = writer; this->writer = writer;
} }
@ -217,13 +217,13 @@ auto Cartridge::parseMarkupEvent(Markup::Node root) -> void {
} }
if(node["id"].text() == "dr") { 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); parseMarkupMap(m, node);
mapping.append(m); mapping.append(m);
} }
if(node["id"].text() == "sr") { if(node["id"].text() == "sr") {
Mapping m({&Event::sr, &event}, [](unsigned, uint8) {}); Mapping m({&Event::sr, &event}, [](uint, uint8) {});
parseMarkupMap(m, node); parseMarkupMap(m, node);
mapping.append(m); 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; hasHitachiDSP = true;
auto rom = root.find("rom"); auto rom = root.find("rom");

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,7 +16,8 @@ auto HitachiDSP::enter() -> void {
if(mmio.dma) { if(mmio.dma) {
for(auto n : range(mmio.dma_length)) { 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); step(2);
} }
mmio.dma = false; mmio.dma = false;
@ -25,7 +26,7 @@ auto HitachiDSP::enter() -> void {
exec(mmio.program_offset); exec(mmio.program_offset);
step(1); step(1);
synchronize_cpu(); synchronizeCPU();
} }
} }

View File

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

View File

@ -1,30 +1,32 @@
auto HitachiDSP::bus_read(uint24 addr) -> uint8 { auto HitachiDSP::bus_read(uint24 addr) -> uint8 {
if((addr & 0x408000) == 0x008000) return bus.read(addr); //$00-3f,80-bf:6000-7fff //todo: read internally, not from Bus
if((addr & 0xf88000) == 0x700000) return bus.read(addr); //$70-77:0000-7fff 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; return 0x00;
} }
auto HitachiDSP::bus_write(uint24 addr, uint8 data) -> void { 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 & 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 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) { if(co_active() == hitachidsp.thread || regs.halt) {
addr = bus.mirror(addr, rom.size()); addr = bus.mirror(addr, rom.size());
//if(Roms == 2 && mmio.r1f52 == 1 && addr >= (bit::round(rom.size()) >> 1)) return 0x00; //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]; 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::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 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 { 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); 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; addr &= 0x1fff;
//Data RAM //Data RAM

View File

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

View File

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

View File

@ -1,5 +1,5 @@
auto ICD2::read(uint addr) -> uint8 { auto ICD2::read(uint addr, uint8 data) -> uint8 {
addr &= 0xffff; addr &= 0x40ffff;
//LY counter //LY counter
if(addr == 0x6000) { if(addr == 0x6000) {
@ -9,7 +9,7 @@ auto ICD2::read(uint addr) -> uint8 {
//command ready port //command ready port
if(addr == 0x6002) { if(addr == 0x6002) {
bool data = packetsize > 0; data = packetsize > 0;
if(data) { if(data) {
for(auto n : range(16)) r7000[n] = packet[0][n]; for(auto n : range(16)) r7000[n] = packet[0][n];
packetsize--; packetsize--;
@ -24,13 +24,13 @@ auto ICD2::read(uint addr) -> uint8 {
} }
//command port //command port
if((addr & 0xfff0) == 0x7000) { if((addr & 0x40fff0) == 0x7000) {
return r7000[addr & 15]; return r7000[addr & 15];
} }
//VRAM port //VRAM port
if(addr == 0x7800) { if(addr == 0x7800) {
uint8 data = output[read_bank * 512 + read_addr]; data = output[read_bank * 512 + read_addr];
read_addr = (read_addr + 1) & 511; read_addr = (read_addr + 1) & 511;
return data; 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 { 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); 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()); 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 { 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 memory_access(write, memory, addr & 0x7fffff, data);
} }
return cpu.regs.mdr; return data;
} }
auto MCC::mcu_read(uint addr) -> uint8 { auto MCC::mcu_read(uint addr, uint8 data) -> uint8 {
return mcu_access(0, addr); return mcu_access(0, addr, data);
} }
auto MCC::mcu_write(uint addr, uint8 data) -> void { auto MCC::mcu_write(uint addr, uint8 data) -> void {
mcu_access(1, addr, data); 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 if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000
uint8 n = (addr >> 16) & 15; uint8 n = (addr >> 16) & 15;
return r[n]; return r[n];
} }
if((addr & 0xf8f000) == 0x105000) { //$10-17:5000-5fff 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; return 0x00;

View File

@ -12,14 +12,14 @@ struct MCC {
auto reset() -> void; auto reset() -> void;
auto memory_access(bool write, Memory& memory, uint addr, uint8 data) -> uint8; 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 memory_write(Memory& memory, uint addr, uint8 data) -> void;
auto mcu_access(bool write, uint addr, uint8 data = 0x00) -> uint8; auto mcu_access(bool write, uint addr, uint8 data) -> uint8;
auto mcu_read(uint addr) -> uint8; auto mcu_read(uint addr, uint8 data) -> uint8;
auto mcu_write(uint addr, uint8 data) -> void; 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_write(uint addr, uint8 data) -> void;
auto mmio_commit() -> void; auto mmio_commit() -> void;

View File

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

View File

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

View File

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

View File

@ -2,10 +2,10 @@ struct NECDSP : Processor::uPD96050, Coprocessor {
static auto Enter() -> void; static auto Enter() -> void;
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 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 writeRAM(uint addr, uint8 data) -> void;
auto init() -> void; auto init() -> void;

View File

@ -23,11 +23,11 @@ auto NSS::set_dip(uint16 dip) -> void {
this->dip = dip; this->dip = dip;
} }
auto NSS::read(uint addr) -> uint8 { auto NSS::read(uint, uint8) -> uint8 {
return dip; 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 reset() -> void;
auto set_dip(uint16 dip) -> 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; auto write(uint addr, uint8 data) -> void;
uint8 dip = 0x00; uint8 dip = 0x00;

View File

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

View File

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

View File

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

View File

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

View File

@ -15,13 +15,13 @@ auto SA1::dma_normal() -> void {
switch(mmio.sd) { switch(mmio.sd) {
case DMA::SourceROM: case DMA::SourceROM:
if((dsa & 0x408000) == 0x008000 || (dsa & 0xc00000) == 0xc00000) { if((dsa & 0x408000) == 0x008000 || (dsa & 0xc00000) == 0xc00000) {
data = bus_read(dsa); data = bus_read(dsa, data);
} }
break; break;
case DMA::SourceBWRAM: case DMA::SourceBWRAM:
if((dsa & 0x40e000) == 0x006000 || (dsa & 0xf00000) == 0x400000) { if((dsa & 0x40e000) == 0x006000 || (dsa & 0xf00000) == 0x400000) {
data = bus_read(dsa); data = bus_read(dsa, data);
} }
break; 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 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 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 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 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 if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
synchronize_cpu(); synchronizeCPU();
return iram.read(addr & 2047); return iram.read(addr & 2047, data);
} }
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
synchronize_cpu(); synchronizeCPU();
return iram.read(addr & 2047); return iram.read(addr & 2047, data);
} }
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
synchronize_cpu(); synchronizeCPU();
return bwram.read(addr & (bwram.size() - 1)); return bwram.read(addr & (bwram.size() - 1), data);
} }
if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff
synchronize_cpu(); synchronizeCPU();
return bitmap_read(addr & 0x0fffff); return bitmap_read(addr & 0x0fffff, data);
} }
//unmapped region //unmapped region
return regs.mdr; return data;
} }
auto SA1::bus_write(uint addr, uint8 data) -> void { 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 if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
synchronize_cpu(); synchronizeCPU();
return iram.write(addr & 2047, data); return iram.write(addr & 2047, data);
} }
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
synchronize_cpu(); synchronizeCPU();
return iram.write(addr & 2047, data); return iram.write(addr & 2047, data);
} }
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
synchronize_cpu(); synchronizeCPU();
return bwram.write(addr & (bwram.size() - 1), data); return bwram.write(addr & (bwram.size() - 1), data);
} }
if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff
synchronize_cpu(); synchronizeCPU();
return bitmap_write(addr & 0x0fffff, data); 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 //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 //to avoid syncing the S-CPU and SA-1*; as both chips are able to access
//these ports. //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 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 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 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 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 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 if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
return iram.read(addr & 2047); return iram.read(addr & 2047, data);
} }
return 0x00; return 0x00;
@ -113,7 +113,7 @@ auto SA1::op_io() -> void {
auto SA1::op_read(uint addr) -> uint8 { auto SA1::op_read(uint addr) -> uint8 {
tick(); tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) 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 { 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); 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 & 0xffffe0) == 0x00ffe0) {
if(addr == 0xffea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0; if(addr == 0xffea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0;
if(addr == 0xffeb && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 8; 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::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 if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size()); 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 cpubwram.read(addr & 0x0fffff);
} }
return cpu.regs.mdr; return data;
} }
auto SA1::mmcbwram_write(uint addr, uint8 data) -> void { 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 { auto SA1::mmc_sa1_read(uint addr, uint8 data) -> uint8 {
synchronize_cpu(); synchronizeCPU();
if(mmio.sw46 == 0) { if(mmio.sw46 == 0) {
//$40-43:0000-ffff x 32 projection //$40-43:0000-ffff x 32 projection
addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), bwram.size()); addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), bwram.size());
return bwram.read(addr); return bwram.read(addr, data);
} else { } else {
//$60-6f:0000-ffff x 128 projection //$60-6f:0000-ffff x 128 projection
addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), 0x100000); 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 { auto SA1::mmc_sa1_write(uint addr, uint8 data) -> void {
synchronize_cpu(); synchronizeCPU();
if(mmio.sw46 == 0) { if(mmio.sw46 == 0) {
//$40-43:0000-ffff x 32 projection //$40-43:0000-ffff x 32 projection
addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), bwram.size()); 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) { if(mmio.bbf == 0) {
//4bpp //4bpp
uint shift = addr & 1; 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 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_io() -> void;
alwaysinline auto op_read(uint addr) -> uint8; alwaysinline auto op_read(uint addr) -> uint8;
alwaysinline auto op_write(uint addr, uint8 data) -> void; 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 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 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 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; auto bitmap_write(uint addr, uint8 data) -> void;

View File

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

View File

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

View File

@ -41,11 +41,11 @@ auto SDD1::reset() -> void {
} }
} }
auto SDD1::read(uint addr) -> uint8 { auto SDD1::read(uint addr, uint8 data) -> uint8 {
addr &= 0xffff; addr &= 0x40ffff;
if((addr & 0x4380) == 0x4300) { if((addr & 0x404380) == 0x4300) {
return cpu.mmio_read(addr); return cpu.mmio_read(addr, data);
} }
switch(addr) { switch(addr) {
@ -55,7 +55,7 @@ auto SDD1::read(uint addr) -> uint8 {
case 0x4807: return mmc[3] >> 20; case 0x4807: return mmc[3] >> 20;
} }
return cpu.regs.mdr; return data;
} }
auto SDD1::write(uint addr, uint8 data) -> void { 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 //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. //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 if(addr < 0x400000) { //(addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
return rom.read(addr); return rom.read(addr);
//addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff); //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::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 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 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 { auto SDD1::mcuram_write(uint addr, uint8 data) -> void {

View File

@ -5,15 +5,15 @@ struct SDD1 {
auto power() -> void; auto power() -> void;
auto reset() -> void; auto reset() -> void;
auto read(uint addr) -> uint8; auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint addr, uint8 data) -> void;
auto mmc_read(uint addr) -> uint8; 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 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 mcuram_write(uint addr, uint8 data) -> void;
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;

View File

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

View File

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

View File

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

View File

@ -14,13 +14,13 @@ struct SPC7110 : Coprocessor {
auto add_clocks(uint clocks) -> void; 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 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 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 mcuram_write(uint addr, uint8 data) -> void;
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;

View File

@ -1,33 +1,33 @@
//ROM / RAM access from the S-CPU //ROM / RAM access from the S-CPU
auto SuperFX::CPUROM::size() const -> unsigned { auto SuperFX::CPUROM::size() const -> uint {
return superfx.rom.size(); 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) { 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, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01,
0x00, 0x01, 0x08, 0x01, 0x00, 0x01, 0x0c, 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); superfx.rom.write(addr, data);
} }
auto SuperFX::CPURAM::size() const -> unsigned { auto SuperFX::CPURAM::size() const -> uint {
return superfx.ram.size(); return superfx.ram.size();
} }
auto SuperFX::CPURAM::read(unsigned addr) -> uint8 { auto SuperFX::CPURAM::read(uint addr, uint8 data) -> uint8 {
if(superfx.regs.sfr.g && superfx.regs.scmr.ran) return cpu.regs.mdr; if(superfx.regs.sfr.g && superfx.regs.scmr.ran) return data;
return superfx.ram.read(addr); 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); superfx.ram.write(addr, data);
} }

View File

@ -1,11 +1,11 @@
struct CPUROM : Memory { struct CPUROM : Memory {
auto size() const -> unsigned; auto size() const -> uint;
auto read(unsigned) -> uint8; auto read(uint, uint8) -> uint8;
auto write(unsigned, uint8) -> void; auto write(uint, uint8) -> void;
} cpurom; } cpurom;
struct CPURAM : Memory { struct CPURAM : Memory {
auto size() const -> unsigned; auto size() const -> uint;
auto read(unsigned) -> uint8; auto read(uint, uint8) -> uint8;
auto write(unsigned, uint8) -> void; auto write(uint, uint8) -> void;
} cpuram; } 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 if((addr & 0xc00000) == 0x000000) { //$00-3f:0000-7fff, $00-3f:8000-ffff
while(!regs.scmr.ron && scheduler.sync != Scheduler::SynchronizeMode::All) { while(!regs.scmr.ron && scheduler.sync != Scheduler::SynchronizeMode::All) {
step(6); step(6);
synchronize_cpu(); synchronizeCPU();
} }
return rom.read((((addr & 0x3f0000) >> 1) | (addr & 0x7fff)) & rom_mask); 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 if((addr & 0xe00000) == 0x400000) { //$40-5f:0000-ffff
while(!regs.scmr.ron && scheduler.sync != Scheduler::SynchronizeMode::All) { while(!regs.scmr.ron && scheduler.sync != Scheduler::SynchronizeMode::All) {
step(6); step(6);
synchronize_cpu(); synchronizeCPU();
} }
return rom.read(addr & rom_mask); 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 if((addr & 0xe00000) == 0x600000) { //$60-7f:0000-ffff
while(!regs.scmr.ran && scheduler.sync != Scheduler::SynchronizeMode::All) { while(!regs.scmr.ran && scheduler.sync != Scheduler::SynchronizeMode::All) {
step(6); step(6);
synchronize_cpu(); synchronizeCPU();
} }
return ram.read(addr & ram_mask); 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 if((addr & 0xe00000) == 0x600000) { //$60-7f:0000-ffff
while(!regs.scmr.ran && scheduler.sync != Scheduler::SynchronizeMode::All) { while(!regs.scmr.ran && scheduler.sync != Scheduler::SynchronizeMode::All) {
step(6); step(6);
synchronize_cpu(); synchronizeCPU();
} }
return ram.write(addr & ram_mask, data); 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(); cpu.synchronizeCoprocessors();
addr &= 0xffff; addr &= 0xffff;
@ -50,7 +50,7 @@ auto SuperFX::mmio_read(unsigned addr) -> uint8 {
return 0x00; return 0x00;
} }
auto SuperFX::mmio_write(unsigned addr, uint8 data) -> void { auto SuperFX::mmio_write(uint addr, uint8 data) -> void {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
addr &= 0xffff; addr &= 0xffff;
@ -59,7 +59,7 @@ auto SuperFX::mmio_write(unsigned addr, uint8 data) -> void {
} }
if(addr >= 0x3000 && addr <= 0x301f) { if(addr >= 0x3000 && addr <= 0x301f) {
unsigned n = (addr >> 1) & 15; uint n = (addr >> 1) & 15;
if((addr & 1) == 0) { if((addr & 1) == 0) {
regs.r[n] = (regs.r[n] & 0xff00) | data; regs.r[n] = (regs.r[n] & 0xff00) | data;
} else { } else {

View File

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

View File

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

View File

@ -78,8 +78,8 @@ auto CPU::enter() -> void {
} else if(status.reset_pending) { } else if(status.reset_pending) {
status.reset_pending = false; status.reset_pending = false;
add_clocks(186); add_clocks(186);
regs.pc.l = bus.read(0xfffc); regs.pc.l = bus.read(0xfffc, regs.mdr);
regs.pc.h = bus.read(0xfffd); regs.pc.h = bus.read(0xfffd, regs.mdr);
} }
} }
@ -93,8 +93,8 @@ auto CPU::op_step() -> void {
} }
auto CPU::enable() -> void { auto CPU::enable() -> void {
function<uint8 (unsigned)> reader{&CPU::mmio_read, (CPU*)&cpu}; function<auto (uint, uint8) -> uint8> reader{&CPU::mmio_read, (CPU*)&cpu};
function<void (unsigned, uint8)> writer{&CPU::mmio_write, (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, 0x00, 0x3f, 0x2140, 0x2183);
bus.map(reader, writer, 0x80, 0xbf, 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, 0x00, 0x3f, 0x4300, 0x437f);
bus.map(reader, writer, 0x80, 0xbf, 0x4300, 0x437f); bus.map(reader, writer, 0x80, 0xbf, 0x4300, 0x437f);
reader = [](unsigned addr) { return cpu.wram[addr]; }; reader = [](uint addr, uint8) -> uint8 { return cpu.wram[addr]; };
writer = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; }; writer = [](uint addr, uint8 data) -> void { cpu.wram[addr] = data; };
bus.map(reader, writer, 0x00, 0x3f, 0x0000, 0x1fff, 0x002000); bus.map(reader, writer, 0x00, 0x3f, 0x0000, 0x1fff, 0x002000);
bus.map(reader, writer, 0x80, 0xbf, 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 { auto CPU::dma_read(uint32 abus) -> uint8 {
if(dma_addr_valid(abus) == false) return 0x00; 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: //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); dma_write(dma_transfer_valid(bbus, abus), 0x2100 | bbus, regs.mdr);
} else { } else {
dma_add_clocks(4); 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_add_clocks(4);
dma_write(dma_addr_valid(abus), abus, regs.mdr); 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); status.clock_count = speed(addr);
dma_edge(); dma_edge();
add_clocks(status.clock_count - 4); add_clocks(status.clock_count - 4);
regs.mdr = bus.read(addr); regs.mdr = bus.read(addr, regs.mdr);
add_clocks(4); add_clocks(4);
alu_edge(); alu_edge();
debugger.op_read(addr, regs.mdr); debugger.op_read(addr, regs.mdr);
@ -44,5 +44,5 @@ auto CPU::speed(uint addr) const -> uint {
} }
auto CPU::disassembler_read(uint32 addr) -> uint8 { 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 //WMDATA
auto CPU::mmio_r2180() -> uint8 { auto CPU::mmio_r2180() -> uint8 {
return bus.read(0x7e0000 | status.wram_addr++); return bus.read(0x7e0000 | status.wram_addr++, regs.mdr);
} }
//WMDATA //WMDATA
@ -405,7 +405,7 @@ auto CPU::mmio_reset() -> void {
alu.shift = 0; alu.shift = 0;
} }
auto CPU::mmio_read(uint addr) -> uint8 { auto CPU::mmio_read(uint addr, uint8 data) -> uint8 {
addr &= 0xffff; addr &= 0xffff;
//APU //APU
@ -416,7 +416,7 @@ auto CPU::mmio_read(uint addr) -> uint8 {
//DMA //DMA
if((addr & 0xff80) == 0x4300) { //$4300-$437f if((addr & 0xff80) == 0x4300) { //$4300-$437f
unsigned i = (addr >> 4) & 7; uint i = (addr >> 4) & 7;
switch(addr & 0xf) { switch(addr & 0xf) {
case 0x0: return mmio_r43x0(i); case 0x0: return mmio_r43x0(i);
case 0x1: return mmio_r43x1(i); case 0x1: return mmio_r43x1(i);
@ -459,7 +459,7 @@ auto CPU::mmio_read(uint addr) -> uint8 {
case 0x421f: return mmio_r421f(); case 0x421f: return mmio_r421f();
} }
return regs.mdr; return data;
} }
auto CPU::mmio_write(uint addr, uint8 data) -> void { auto CPU::mmio_write(uint addr, uint8 data) -> void {
@ -474,7 +474,7 @@ auto CPU::mmio_write(uint addr, uint8 data) -> void {
//DMA //DMA
if((addr & 0xff80) == 0x4300) { //$4300-$437f if((addr & 0xff80) == 0x4300) { //$4300-$437f
unsigned i = (addr >> 4) & 7; uint i = (addr >> 4) & 7;
switch(addr & 0xf) { switch(addr & 0xf) {
case 0x0: mmio_w43x0(i, data); return; case 0x0: mmio_w43x0(i, data); return;
case 0x1: mmio_w43x1(i, data); return; case 0x1: mmio_w43x1(i, data); return;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -94,8 +94,8 @@ auto PPU::add_clocks(uint clocks) -> void {
} }
auto PPU::enable() -> void { auto PPU::enable() -> void {
function<uint8 (unsigned)> reader{&PPU::mmio_read, (PPU*)&ppu}; function<auto (uint, uint8) -> uint8> reader{&PPU::mmio_read, (PPU*)&ppu};
function<void (unsigned, uint8)> writer{&PPU::mmio_write, (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, 0x00, 0x3f, 0x2100, 0x213f);
bus.map(reader, writer, 0x80, 0xbf, 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); memory.write_protect(!regs.write_enable);
} }
auto SatellaviewCartridge::size() const -> unsigned { auto SatellaviewCartridge::size() const -> uint {
return memory.size(); return memory.size();
} }
auto SatellaviewCartridge::read(unsigned addr) -> uint8 { auto SatellaviewCartridge::read(uint addr, uint8 data) -> uint8 {
if(readonly) return memory.read(bus.mirror(addr, memory.size())); if(readonly) return memory.read(bus.mirror(addr, memory.size()), data);
if(addr == 0x0002) { if(addr == 0x0002) {
if(regs.flash_enable) return 0x80; 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(readonly) return;
if((addr & 0xff0000) == 0) { if((addr & 0xff0000) == 0) {

View File

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