Kernel: Implemented SharedMemory Kernel Object

HID: Added support for button input
QT: Added dialogue for remapping keys
This commit is contained in:
inspuration 2014-06-12 14:01:05 -04:00
parent c34ba38001
commit 5346cfe3e8
28 changed files with 762 additions and 29 deletions

View file

@ -7,6 +7,7 @@ set(SRCS
debugger/ramview.cpp
debugger/registers.cpp
hotkeys.cpp
key_bindings.cpp
main.cpp
config/controller_config.cpp
config/controller_config_util.cpp)
@ -17,11 +18,13 @@ set (HEADERS
debugger/ramview.hxx
debugger/registers.hxx
hotkeys.hxx
key_bindings.hxx
main.hxx
ui_callstack.h
ui_controller_config.h
ui_disassembler.h
ui_hotkeys.h
ui_key_bindings.h
ui_main.h
ui_registers.h
version.h
@ -33,6 +36,7 @@ qt4_wrap_ui(UI_HDRS
debugger/disassembler.ui
debugger/registers.ui
hotkeys.ui
key_bindings.ui
main.ui
config/controller_config.ui)
@ -45,6 +49,7 @@ qt4_wrap_cpp(MOC_SRCS
debugger/registers.hxx
debugger/ramview.hxx
hotkeys.hxx
key_bindings.hxx
main.hxx
config/controller_config.hxx
config/controller_config_util.hxx)

View file

@ -3,10 +3,13 @@
#include "common/common.h"
#include "bootmanager.hxx"
#include "key_bindings.hxx"
#include "core/core.h"
#include "core/loader.h"
#include "core/hw/hw.h"
#include "core/hw/hid.h"
#include "video_core/video_core.h"
@ -119,6 +122,8 @@ GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this
setLayout(layout);
BackupGeometry();
buttonReg = 0x0;
}
GRenderWindow::~GRenderWindow()
@ -198,6 +203,11 @@ void GRenderWindow::keyPressEvent(QKeyEvent* event)
if (!key_processed)
QWidget::keyPressEvent(event);
*/
buttonReg |= GetKeyBinding(event);
HID::SetButtonReg(buttonReg);
return;
}
void GRenderWindow::keyReleaseEvent(QKeyEvent* event)
@ -211,4 +221,7 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event)
if (!key_processed)
QWidget::keyPressEvent(event);
*/
buttonReg &= 0xffffffff ^ GetKeyBinding(event);
HID::SetButtonReg(buttonReg);
}

View file

@ -1,5 +1,6 @@
#include <QThread>
#include <QGLWidget>
#include <map>
#include "common/common.h"
#include "common/emu_window.h"
@ -109,4 +110,6 @@ private:
EmuThread emu_thread;
QByteArray geometry;
u32 buttonReg;
};

View file

@ -137,6 +137,7 @@
<ClCompile Include="debugger\ramview.cpp" />
<ClCompile Include="bootmanager.cpp" />
<ClCompile Include="hotkeys.cpp" />
<ClCompile Include="key_bindings.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
@ -152,6 +153,7 @@
<MOC Include="debugger\registers.hxx" />
<MOC Include="bootmanager.hxx" />
<MOC Include="hotkeys.hxx" />
<MOC Include="key_bindings.hxx" />
<MOC Include="main.hxx" />
</ItemGroup>
<ItemGroup>
@ -177,6 +179,7 @@
<UIC Include="debugger\registers.ui" />
<UIC Include="debugger\disassembler.ui" />
<UIC Include="hotkeys.ui" />
<UIC Include="key_bindings.ui" />
<UIC Include="main.ui" />
</ItemGroup>
<ItemGroup>

View file

@ -51,6 +51,7 @@
<ClCompile Include="debugger\registers.cpp">
<Filter>debugger</Filter>
</ClCompile>
<ClCompile Include="key_bindings.cpp" />
</ItemGroup>
<ItemGroup>
<MOC Include="..\..\externals\qhexedit\commands.h">
@ -86,6 +87,7 @@
<MOC Include="debugger\registers.hxx">
<Filter>debugger</Filter>
</MOC>
<MOC Include="key_bindings.hxx" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="version.h" />
@ -114,6 +116,7 @@
<UIC Include="debugger\registers.ui">
<Filter>debugger</Filter>
</UIC>
<UIC Include="key_bindings.ui" />
</ItemGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />

View file

@ -17,6 +17,7 @@ GPUCommandListModel::GPUCommandListModel(QObject* parent) : QAbstractItemModel(p
QModelIndex GPUCommandListModel::index(int row, int column, const QModelIndex& parent) const
{
TreeItem* item;
TreeItem* internal;
if (!parent.isValid()) {
item = root_item;
@ -24,7 +25,13 @@ QModelIndex GPUCommandListModel::index(int row, int column, const QModelIndex& p
item = (TreeItem*)parent.internalPointer();
}
return createIndex(row, column, item->children[row]);
if (item->children.size() <= row) {
internal = item;
}
else { internal = item->children[row]; }
return createIndex(row, column, internal);
}
QModelIndex GPUCommandListModel::parent(const QModelIndex& child) const

View file

@ -0,0 +1,143 @@
#include <QKeySequence>
#include <QStyledItemDelegate>
#include <QSettings>
#include <QKeyEvent>
#include "key_bindings.hxx"
#include <map>
#include "core/hw/hid.h"
typedef std::map<QKeySequence, HID::PAD> BindingsMap;
BindingsMap bindings;
typedef std::map<HID::PAD, QKeySequence> ReverseBindingsMap;
ReverseBindingsMap reverseBindings;
typedef std::map<HID::PAD, QString> NameMap;
NameMap names;
typedef std::map<QString, HID::PAD> ReverseNameMap;
ReverseNameMap reverseNames;
void SaveKeyBindings(QSettings& settings)
{
settings.beginGroup("KeyBindings");
for (BindingsMap::iterator group = bindings.begin(); group != bindings.end(); ++group)
{
settings.setValue(group->first.toString(), group->second);
settings.endGroup();
}
settings.endGroup();
}
void LoadKeyBindings(QSettings& settings)
{
settings.beginGroup("KeyBindings");
// Make sure NOT to use a reference here because it would become invalid once we call beginGroup()
QStringList keys = settings.allKeys();
for (QList<QString>::iterator key = keys.begin(); key != keys.end(); ++key)
{
settings.beginGroup(*key);
QKeySequence keyseq = QKeySequence::fromString(settings.value("").toString());
}
settings.endGroup();
}
HID::PAD GetKeyBinding(QKeyEvent * event)
{
QKeySequence keySeq = QKeySequence(event->text());
return bindings[keySeq];
}
void RegisterKeyBinding(const QKeySequence keySeq, const HID::PAD pad)
{
bindings[keySeq] = pad;
reverseBindings[pad] = keySeq;
}
void createNameMap() {
for (int i = 0; i < HID::numPadItems; i++){
names[(HID::PAD)(1 << i)] = QString(HID::PAD_NAMES[i]);
reverseNames[QString(HID::PAD_NAMES[i])] = (HID::PAD)(1 << i);
}
}
void setDefaultKeyBindings() {
RegisterKeyBinding(QKeySequence("Y"), HID::PAD::PAD_A);
RegisterKeyBinding(QKeySequence("H"), HID::PAD::PAD_B);
RegisterKeyBinding(QKeySequence("Z"), HID::PAD::PAD_SELECT);
RegisterKeyBinding(QKeySequence("X"), HID::PAD::PAD_START);
RegisterKeyBinding(QKeySequence("W"), HID::PAD::PAD_UP);
RegisterKeyBinding(QKeySequence("A"), HID::PAD::PAD_LEFT);
RegisterKeyBinding(QKeySequence("S"), HID::PAD::PAD_DOWN);
RegisterKeyBinding(QKeySequence("D"), HID::PAD::PAD_RIGHT);
RegisterKeyBinding(QKeySequence("6"), HID::PAD::PAD_R);
RegisterKeyBinding(QKeySequence("7"), HID::PAD::PAD_L);
RegisterKeyBinding(QKeySequence("U"), HID::PAD::PAD_X);
RegisterKeyBinding(QKeySequence("J"), HID::PAD::PAD_Y);
}
//class makes single columns uneditable
class NoEditDelegate : public QStyledItemDelegate {
public:
NoEditDelegate(QObject* parent = 0) : QStyledItemDelegate(parent) {}
virtual QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
return 0;
}
};
void GKeyBindingsDialog::updateItem(QTreeWidgetItem * item, int column) {
bindings[item->text(1)] = reverseNames[item->text(0)]; //TODO: sanitise
reverseBindings[reverseNames[item->text(0)]] = item->text(1);
return;
}
GKeyBindingsDialog::GKeyBindingsDialog(QWidget* parent) : QDialog(parent)
{
ui.setupUi(this);
createNameMap();
for (NameMap::iterator key = names.begin(); key != names.end(); ++key)
{
QKeySequence keySeq = reverseBindings[key->first];
QStringList columns;
columns << key->second << keySeq.toString();
QTreeWidgetItem* item = new QTreeWidgetItem(columns);
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
ui.treeWidget->addTopLevelItem(item);
}
// TODO: Make context configurable as well (hiding the column for now)
ui.treeWidget->setEditTriggers(
QAbstractItemView::EditKeyPressed
| QAbstractItemView::SelectedClicked
| QAbstractItemView::AnyKeyPressed
);
connect(
this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
this, SLOT(OnMouseDoubleClicked(QTreeWidgetItem*, int))
);
ui.treeWidget->setColumnCount(2);
ui.treeWidget->resizeColumnToContents(0);
ui.treeWidget->resizeColumnToContents(1);
connect(ui.treeWidget, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
this, SLOT(updateItem(QTreeWidgetItem *, int)));
ui.treeWidget->setItemDelegateForColumn(0, new NoEditDelegate(this));
}

View file

@ -0,0 +1,62 @@
#include <QDialog>
#include "ui_key_bindings.h"
#include "core/hw/hid.h"
class QSettings;
/**
* Register a hotkey.
*
* @param key Keyboard button
* @param pad Name of the pad
*/
void RegisterKeyBinding(const QKeySequence keySeq, const HID::PAD pad);
/**
* Saves all key bindings to the settings file.
*
*
*/
void SaveKeyBindings(QSettings& settings);
/**
* Get PAD associated with key event
*
*
*/
HID::PAD GetKeyBinding(QKeyEvent * event);
/**
* Loads key bindings from the settings file.
*
*
*/
void LoadKeyBindings(QSettings& settings);
/**
* Sets default key bindings.
*
*
*/
void setDefaultKeyBindings();
class GKeyBindingsDialog : public QDialog
{
Q_OBJECT
public:
GKeyBindingsDialog(QWidget* parent = NULL);
private:
Ui::key_bindings ui;
private slots:
void updateItem(QTreeWidgetItem * item, int column);
};

View file

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>key_bindings</class>
<widget class="QDialog" name="key_bindings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>363</width>
<height>388</height>
</rect>
</property>
<property name="windowTitle">
<string>Key Bindings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeWidget" name="treeWidget">
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectItems</enum>
</property>
<property name="headerHidden">
<bool>false</bool>
</property>
<column>
<property name="text">
<string>Action</string>
</property>
</column>
<column>
<property name="text">
<string>Key</string>
</property>
</column>
<column>
<property name="text">
<string>Pad</string>
</property>
</column>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>key_bindings</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>key_bindings</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -13,6 +13,7 @@
#include "bootmanager.hxx"
#include "hotkeys.hxx"
#include "key_bindings.hxx"
//debugger
#include "debugger/disassembler.hxx"
@ -92,7 +93,8 @@ GMainWindow::GMainWindow()
connect(ui.action_Pause, SIGNAL(triggered()), this, SLOT(OnPauseGame()));
connect(ui.action_Stop, SIGNAL(triggered()), this, SLOT(OnStopGame()));
connect(ui.action_Popout_Window_Mode, SIGNAL(triggered(bool)), this, SLOT(ToggleWindowMode()));
connect(ui.action_Hotkeys, SIGNAL(triggered()), this, SLOT(OnOpenHotkeysDialog()));
connect(ui.action_Hotkeys, SIGNAL(triggered()), this, SLOT(OnOpenHotkeysDialog()));\
connect(ui.action_Key_Bindings, SIGNAL(triggered()), this, SLOT(OnOpenKeyBindingsDialog()));
// BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views before the CPU continues
connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), disasmWidget, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection);
@ -107,6 +109,11 @@ GMainWindow::GMainWindow()
connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, SLOT(OnMenuLoadFile()));
connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame()));
// Setup key bindings
setDefaultKeyBindings();
LoadKeyBindings(settings);
setWindowTitle(render_window->GetWindowTitle().c_str());
show();
@ -199,6 +206,13 @@ void GMainWindow::OnOpenHotkeysDialog()
}
void GMainWindow::OnOpenKeyBindingsDialog()
{
GKeyBindingsDialog dialog(this);
dialog.exec();
}
void GMainWindow::ToggleWindowMode()
{
bool enable = ui.action_Popout_Window_Mode->isChecked();

View file

@ -41,6 +41,7 @@ private slots:
void OnMenuLoadFile();
void OnMenuLoadSymbolMap();
void OnOpenHotkeysDialog();
void OnOpenKeyBindingsDialog();
void OnConfigure();
void ToggleWindowMode();

View file

@ -53,6 +53,7 @@
<addaction name="action_Stop"/>
<addaction name="separator"/>
<addaction name="action_Configure"/>
<addaction name="action_Key_Bindings"/>
</widget>
<widget class="QMenu" name="menu_View">
<property name="title">
@ -127,6 +128,11 @@
<string>Configure &amp;Hotkeys ...</string>
</property>
</action>
<action name="action_Key_Bindings">
<property name="text">
<string>Set Key Bindings</string>
</property>
</action>
<action name="action_Configure">
<property name="text">
<string>Configure ...</string>

View file

@ -0,0 +1,77 @@
/********************************************************************************
** Form generated from reading UI file 'key_bindings.ui'
**
** Created by: Qt User Interface Compiler version 4.8.6
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_KEY_BINDINGS_H
#define UI_KEY_BINDINGS_H
#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QDialog>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QHeaderView>
#include <QtGui/QTreeWidget>
#include <QtGui/QVBoxLayout>
QT_BEGIN_NAMESPACE
class Ui_key_bindings
{
public:
QVBoxLayout *verticalLayout;
QTreeWidget *treeWidget;
QDialogButtonBox *buttonBox;
void setupUi(QDialog *key_bindings)
{
if (key_bindings->objectName().isEmpty())
key_bindings->setObjectName(QString::fromUtf8("key_bindings"));
key_bindings->resize(363, 388);
verticalLayout = new QVBoxLayout(key_bindings);
verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
treeWidget = new QTreeWidget(key_bindings);
treeWidget->setObjectName(QString::fromUtf8("treeWidget"));
treeWidget->setSelectionBehavior(QAbstractItemView::SelectItems);
treeWidget->setHeaderHidden(false);
verticalLayout->addWidget(treeWidget);
buttonBox = new QDialogButtonBox(key_bindings);
buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset);
verticalLayout->addWidget(buttonBox);
retranslateUi(key_bindings);
QObject::connect(buttonBox, SIGNAL(accepted()), key_bindings, SLOT(accept()));
QObject::connect(buttonBox, SIGNAL(rejected()), key_bindings, SLOT(reject()));
QMetaObject::connectSlotsByName(key_bindings);
} // setupUi
void retranslateUi(QDialog *key_bindings)
{
key_bindings->setWindowTitle(QApplication::translate("key_bindings", "Key Bindings", 0, QApplication::UnicodeUTF8));
QTreeWidgetItem *___qtreewidgetitem = treeWidget->headerItem();
___qtreewidgetitem->setText(2, QApplication::translate("key_bindings", "Pad", 0, QApplication::UnicodeUTF8));
___qtreewidgetitem->setText(1, QApplication::translate("key_bindings", "Key", 0, QApplication::UnicodeUTF8));
___qtreewidgetitem->setText(0, QApplication::translate("key_bindings", "Action", 0, QApplication::UnicodeUTF8));
} // retranslateUi
};
namespace Ui {
class key_bindings: public Ui_key_bindings {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_KEY_BINDINGS_H

View file

@ -30,18 +30,18 @@
<ClInclude Include="msg_handler.h" />
<ClInclude Include="platform.h" />
<ClInclude Include="register_set.h" />
<ClInclude Include="scm_rev.h" />
<ClInclude Include="std_condition_variable.h" />
<ClInclude Include="std_mutex.h" />
<ClInclude Include="std_thread.h" />
<ClInclude Include="string_util.h" />
<ClInclude Include="swap.h" />
<ClInclude Include="symbols.h" />
<ClInclude Include="thread.h" />
<ClInclude Include="thread_queue_list.h" />
<ClInclude Include="thunk.h" />
<ClInclude Include="timer.h" />
<ClInclude Include="utf8.h" />
<ClInclude Include="symbols.h" />
<ClInclude Include="scm_rev.h" />
<ClInclude Include="thread_queue_list.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="break_points.cpp" />
@ -56,14 +56,18 @@
<ClCompile Include="memory_util.cpp" />
<ClCompile Include="misc.cpp" />
<ClCompile Include="msg_handler.cpp" />
<ClCompile Include="scm_rev.cpp" />
<ClCompile Include="string_util.cpp" />
<ClCompile Include="symbols.cpp" />
<ClCompile Include="thread.cpp" />
<ClCompile Include="timer.cpp" />
<ClCompile Include="utf8.cpp" />
<ClCompile Include="symbols.cpp" />
<ClCompile Include="scm_rev.cpp" />
</ItemGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<None Include="scm_rev.cpp.in" />
<None Include="scm_rev_gen.js" />
</ItemGroup>
</Project>

View file

@ -64,6 +64,7 @@ enum LOG_TYPE {
HW,
TIME,
NETPLAY,
HID,
NUMBER_OF_LOGS // Must be last
};

View file

@ -73,6 +73,7 @@ LogManager::LogManager()
m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager");
m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
m_Log[LogTypes::HID] = new LogContainer("HID", "Human Interface Devices");
m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str());
m_consoleLog = new ConsoleListener();

View file

@ -36,6 +36,7 @@ set(SRCS core.cpp
hle/svc.cpp
hle/kernel/kernel.cpp
hle/kernel/mutex.cpp
hle/kernel/shared_memory.cpp
hle/kernel/thread.cpp
hle/service/apt.cpp
hle/service/gsp.cpp
@ -44,7 +45,8 @@ set(SRCS core.cpp
hle/service/srv.cpp
hw/gpu.cpp
hw/hw.cpp
hw/ndma.cpp)
hw/ndma.cpp
hw/hid.cpp)
set(HEADERS core.h
core_timing.h
@ -81,6 +83,7 @@ set(HEADERS core.h
hle/svc.h
hle/kernel/kernel.h
hle/kernel/mutex.h
hle/kernel/shared_memory.h
hle/kernel/thread.h
hle/function_wrappers.h
hle/service/apt.h
@ -90,6 +93,7 @@ set(HEADERS core.h
hle/service/srv.h
hw/gpu.h
hw/hw.h
hw/ndma.h)
hw/ndma.h
hw/hid.h)
add_library(core STATIC ${SRCS} ${HEADERS})

View file

@ -99,6 +99,9 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<ClCompile />
<ClCompile>
<ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile />
@ -106,6 +109,9 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<ClCompile />
<ClCompile>
<ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile />
@ -120,6 +126,7 @@
<FloatingPointModel>Fast</FloatingPointModel>
<BufferSecurityCheck>false</BufferSecurityCheck>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -130,6 +137,9 @@
<OptimizeReferences>true</OptimizeReferences>
</Link>
<ClCompile />
<ClCompile>
<ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\common\common.vcxproj">
@ -170,6 +180,7 @@
<ClCompile Include="hle\hle.cpp" />
<ClCompile Include="hle\kernel\kernel.cpp" />
<ClCompile Include="hle\kernel\mutex.cpp" />
<ClCompile Include="hle\kernel\shared_memory.cpp" />
<ClCompile Include="hle\kernel\thread.cpp" />
<ClCompile Include="hle\service\apt.cpp" />
<ClCompile Include="hle\service\gsp.cpp" />
@ -178,6 +189,7 @@
<ClCompile Include="hle\service\srv.cpp" />
<ClCompile Include="hle\svc.cpp" />
<ClCompile Include="hw\gpu.cpp" />
<ClCompile Include="hw\hid.cpp" />
<ClCompile Include="hw\hw.cpp" />
<ClCompile Include="hw\ndma.cpp" />
<ClCompile Include="loader.cpp" />
@ -219,6 +231,7 @@
<ClInclude Include="hle\hle.h" />
<ClInclude Include="hle\kernel\kernel.h" />
<ClInclude Include="hle\kernel\mutex.h" />
<ClInclude Include="hle\kernel\shared_memory.h" />
<ClInclude Include="hle\kernel\thread.h" />
<ClInclude Include="hle\service\apt.h" />
<ClInclude Include="hle\service\gsp.h" />
@ -227,6 +240,7 @@
<ClInclude Include="hle\service\srv.h" />
<ClInclude Include="hle\svc.h" />
<ClInclude Include="hw\gpu.h" />
<ClInclude Include="hw\hid.h" />
<ClInclude Include="hw\hw.h" />
<ClInclude Include="hw\ndma.h" />
<ClInclude Include="loader.h" />

View file

@ -165,6 +165,12 @@
<ClCompile Include="arm\interpreter\armcopro.cpp">
<Filter>arm\interpreter</Filter>
</ClCompile>
<ClCompile Include="hw\hid.cpp">
<Filter>hw</Filter>
</ClCompile>
<ClCompile Include="hle\kernel\shared_memory.cpp">
<Filter>hle\kernel</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="arm\disassembler\arm_disasm.h">
@ -295,6 +301,12 @@
<ClInclude Include="hle\kernel\mutex.h">
<Filter>hle\kernel</Filter>
</ClInclude>
<ClInclude Include="hw\hid.h">
<Filter>hw</Filter>
</ClInclude>
<ClInclude Include="hle\kernel\shared_memory.h">
<Filter>hle\kernel</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />

View file

@ -0,0 +1,98 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <map>
#include <vector>
#include "common/common.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/thread.h"
namespace Kernel {
class SharedMemory : public Object {
public:
const char* GetTypeName() { return "SharedMemory"; }
static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; }
Kernel::HandleType GetHandleType() const { return Kernel::HandleType::SharedMemory; }
//TODO: implement
/**
* Wait for kernel object to synchronize
* @param wait Boolean wait set if current thread should wait as a result of sync operation
* @return Result of operation, 0 on success, otherwise error code
*/
Result WaitSynchronization(bool* wait) {
// TODO(bravia): ImplementMe
return 0;
}
template <typename T>
inline void Read(T &var, const u32 addr);
template <typename T>
inline void Write(T &var, const u32 addr);
u32 size;
u8* mem_ptr = NULL;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
SharedMemory* CreateSharedMemory(Handle& handle, u32 size) {
SharedMemory* mem = new SharedMemory;
handle = Kernel::g_object_pool.Create(mem);
mem->size = size;
return mem;
}
Handle CreateSharedMemory(u32 size) {
Handle handle;
SharedMemory* mem = CreateSharedMemory(handle, size);
return handle;
}
u32 GetSharedMemorySize(Handle handle) {
SharedMemory* mem = Kernel::g_object_pool.GetFast<SharedMemory>(handle);
_assert_msg_(KERNEL, (mem != nullptr), "called, but mem is nullptr!");
return mem->size;
}
void SetSharedMemoryPointer(Handle handle, u8* ptr) {
SharedMemory* mem = Kernel::g_object_pool.GetFast<SharedMemory>(handle);
_assert_msg_(KERNEL, (mem != nullptr), "called, but mem is nullptr!");
mem->mem_ptr = ptr;
}
template <typename T>
inline void ReadSharedMemory(Handle handle, T &var, const u32 addr) {
SharedMemory* mem = Kernel::g_object_pool.GetFast<SharedMemory>(handle);
_assert_msg_(KERNEL, (mem != nullptr), "called, but mem is nullptr!");
if (mem->mem_ptr!=NULL)
var = *((const T*)&mem->mem_ptr[addr & (mem->size - 1)]);
}
template <typename T>
inline void WriteSharedMemory(Handle handle, const T data, const u32 addr) {
SharedMemory* mem = Kernel::g_object_pool.GetFast<SharedMemory>(handle);
_assert_msg_(KERNEL, (mem != nullptr), "called, but mem is nullptr!");
if (mem->mem_ptr != NULL)
*(T*)&mem->mem_ptr[addr & (mem->size - 1)] = data;
}
template void WriteSharedMemory<u64>(Handle handle, const u64 data, const u32 addr);
template void WriteSharedMemory<u32>(Handle handle, const u32 data, const u32 addr);
template void WriteSharedMemory<u16>(Handle handle, const u16 data, const u32 addr);
template void WriteSharedMemory<u8>(Handle handle, const u8 data, const u32 addr);
template void ReadSharedMemory<u64>(Handle handle, u64 &var, const u32 addr);
template void ReadSharedMemory<u32>(Handle handle, u32 &var, const u32 addr);
template void ReadSharedMemory<u16>(Handle handle, u16 &var, const u32 addr);
template void ReadSharedMemory<u8>(Handle handle, u8 &var, const u32 addr);
} // namespace

View file

@ -0,0 +1,30 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include "common/common_types.h"
#include "core/hle/kernel/kernel.h"
namespace Kernel {
/**
* Creates a shared memory object
* @param handle Reference to handle for the newly created mutex
* @param
*/
Handle CreateSharedMemory(u32 size);
u32 GetSharedMemorySize(Handle handle);
void SetSharedMemoryPointer(Handle handle, u8* ptr);
template <typename T>
inline void ReadSharedMemory(Handle handle, T &var, const u32 addr);
template <typename T>
inline void WriteSharedMemory(Handle handle, const T data, const u32 addr);
} // namespace

View file

@ -8,6 +8,7 @@
#include "core/mem_map.h"
#include "core/hle/hle.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/service/gsp.h"
#include "core/hw/gpu.h"
@ -19,6 +20,10 @@
// Main graphics debugger object - TODO: Here is probably not the best place for this
GraphicsDebugger g_debugger;
//Handle to irq memory
Handle memIRQ;
/// GSP shared memory GX command buffer header
union GX_CmdBufferHeader {
u32 hex;
@ -107,6 +112,8 @@ void RegisterInterruptRelayQueue(Service::Interface* self) {
u32 event_handle = cmd_buff[3]; // TODO(bunnei): Implement event handling
cmd_buff[2] = g_thread_id; // ThreadID
memIRQ = Kernel::CreateSharedMemory(0x1000); //page size for now
cmd_buff[4] = memIRQ;
}

View file

@ -6,18 +6,31 @@
#include "core/hle/hle.h"
#include "core/hle/service/hid.h"
#include "core/hle/kernel/shared_memory.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// Namespace HID_User
namespace HID_User {
Handle g_mem_ipc = NULL;
Handle GetMemIPCHandle() {
return g_mem_ipc;
}
void GetIPCHandles(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
g_mem_ipc = Kernel::CreateSharedMemory(0x1000); //page size for now
cmd_buff[3] = g_mem_ipc;
}
const Interface::FunctionInfo FunctionTable[] = {
{0x000A0000, NULL, "GetIPCHandles"},
{0x00110000, NULL, "EnableAccelerometer"},
{0x00130000, NULL, "EnableGyroscopeLow"},
{0x00150000, NULL, "GetGyroscopeLowRawToDpsCoefficient"},
{0x00160000, NULL, "GetGyroscopeLowCalibrateParam"},
{0x000A0000, GetIPCHandles, "GetIPCHandles" },
{0x00110000, nullptr, "EnableAccelerometer"},
{0x00130000, nullptr, "EnableGyroscopeLow"},
{0x00150000, nullptr, "GetGyroscopeLowRawToDpsCoefficient"},
{0x00160000, nullptr, "GetGyroscopeLowCalibrateParam"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View file

@ -14,6 +14,8 @@
namespace HID_User {
Handle GetMemIPCHandle();
class Interface : public Service::Interface {
public:

28
src/core/hw/hid.cpp Normal file
View file

@ -0,0 +1,28 @@
#include "hid.h"
#include "core/hle/service/hid.h"
#include "core/hle/kernel/shared_memory.h"
namespace HID {
void SetButtonReg(u32 buttonData) {
Handle sharedMem = HID_User::GetMemIPCHandle();
if (sharedMem != NULL)
Kernel::WriteSharedMemory(sharedMem, buttonData, OFFSET_BUTTONS);
}
/// Update hardware
void Update() {
}
/// Initialize hardware
void Init() {
NOTICE_LOG(HID, "initialized OK");
}
/// Shutdown hardware
void Shutdown() {
NOTICE_LOG(HID, "shutdown OK");
}
}

67
src/core/hw/hid.h Normal file
View file

@ -0,0 +1,67 @@
#pragma once
#include "common/common_types.h"
#include "core/mem_map.h"
namespace HID {
struct Registers {
u32 buttons;
//u32 pad1; etc...
};
extern Registers g_regs;
enum {
OFFSET_BUTTONS = 0x1c, //TODO: it works using the shared mem mapping with all homebrew tested, however the wiki states 0x10146000 as the paddr
};
enum {
REG_BUTTONS = 0x1EC46000 //does not work due to confusion between shared mem and hardware IO
};
const int numPadItems = 12; // figure out a better way :(
enum PAD {
PAD_A = (1 << 0),
PAD_B = (1 << 1),
PAD_SELECT = (1 << 2),
PAD_START = (1 << 3),
PAD_RIGHT = (1 << 4),
PAD_LEFT = (1 << 5),
PAD_UP = (1 << 6),
PAD_DOWN = (1 << 7),
PAD_R = (1 << 8),
PAD_L = (1 << 9),
PAD_X = (1 << 10),
PAD_Y = (1 << 11),
};
char * const PAD_NAMES[] = {
"PAD_A",
"PAD_B",
"PAD_SELECT",
"PAD_START",
"PAD_RIGHT",
"PAD_LEFT",
"PAD_UP",
"PAD_DOWN",
"PAD_R",
"PAD_L",
"PAD_X",
"PAD_Y"
};
void SetButtonReg(u32 buttonData);
/// Update hardware
void Update();
/// Initialize hardware
void Init();
/// Shutdown hardware
void Shutdown();
}

View file

@ -8,6 +8,8 @@
#include "core/hw/hw.h"
#include "core/hw/gpu.h"
#include "core/hw/ndma.h"
#include "core/hw/hid.h"
namespace HW {
@ -89,12 +91,14 @@ template void Write<u8>(u32 addr, const u8 data);
void Update() {
GPU::Update();
NDMA::Update();
HID::Update();
}
/// Initialize hardware
void Init() {
GPU::Init();
NDMA::Init();
HID::Init();
NOTICE_LOG(HW, "initialized OK");
}

View file

@ -9,6 +9,8 @@
#include "core/mem_map.h"
#include "core/hw/hw.h"
#include "hle/hle.h"
#include "hle/kernel/kernel.h"
#include "hle/kernel/shared_memory.h"
#include "hle/config_mem.h"
namespace Memory {
@ -71,8 +73,15 @@ inline void _Read(T &var, const u32 addr) {
// Shared memory
} else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
var = *((const T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK]);
for (std::map<u32, MemoryBlock>::iterator it = g_shared_map.begin(); it != g_shared_map.end(); it++) {
MemoryBlock block = it->second;
if ((vaddr >= block.base_address) && (vaddr < block.GetVirtualAddress())) {
Handle handle = block.handle;
Kernel::ReadSharedMemory<T>(handle, var, addr);
return;
}
}
ERROR_LOG(MEMMAP, "Read from unknown shared mapping : Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
// System memory
} else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
var = *((const T*)&g_system_mem[vaddr & SYSTEM_MEMORY_MASK]);
@ -86,7 +95,7 @@ inline void _Read(T &var, const u32 addr) {
var = *((const T*)&g_vram[vaddr & VRAM_MASK]);
} else {
//_assert_msg_(MEMMAP, false, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
ERROR_LOG(MEMMAP, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
}
}
@ -117,7 +126,15 @@ inline void _Write(u32 addr, const T data) {
// Shared memory
} else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
*(T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK] = data;
for (std::map<u32, MemoryBlock>::iterator it = g_shared_map.begin(); it != g_shared_map.end(); it++) {
MemoryBlock block = it->second;
if ((vaddr >= block.base_address) && (vaddr < block.base_address + block.size)) {
Handle handle = block.handle;
Kernel::WriteSharedMemory<T>(handle, data, addr);
return;
}
}
ERROR_LOG(MEMMAP, "Write to unknown shared mapping : Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, vaddr);
// System memory
} else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
@ -136,8 +153,7 @@ inline void _Write(u32 addr, const T data) {
// Error out...
} else {
_assert_msg_(MEMMAP, false, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8,
data, vaddr);
ERROR_LOG(MEMMAP, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, vaddr);
}
}
@ -188,6 +204,7 @@ u32 MapBlock_Shared(u32 handle, u32 addr,u32 permissions) {
MemoryBlock block;
block.handle = handle;
block.size = Kernel::GetSharedMemorySize(handle);
block.base_address = addr;
block.permissions = permissions;
@ -195,9 +212,14 @@ u32 MapBlock_Shared(u32 handle, u32 addr,u32 permissions) {
const MemoryBlock last_block = g_shared_map.rbegin()->second;
block.address = last_block.address + last_block.size;
}
g_shared_map[block.GetVirtualAddress()] = block;
return block.GetVirtualAddress();
u32 vaddr = block.GetVirtualAddress();
g_shared_map[vaddr] = block;
Kernel::SetSharedMemoryPointer(handle, &g_shared_mem[vaddr & SHARED_MEMORY_MASK]);
return vaddr;
}
/**