diff options
Diffstat (limited to 'src')
35 files changed, 857 insertions, 385 deletions
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 89aae7ce6..76e0c68c3 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include "core/system.h" | 23 | #include "core/system.h" |
| 24 | #include "core/loader.h" | 24 | #include "core/loader.h" |
| 25 | #include "core/core.h" | 25 | #include "core/core.h" |
| 26 | #include "core/arm/disassembler/load_symbol_map.h" | ||
| 26 | #include "version.h" | 27 | #include "version.h" |
| 27 | 28 | ||
| 28 | 29 | ||
| @@ -74,6 +75,7 @@ GMainWindow::GMainWindow() | |||
| 74 | 75 | ||
| 75 | // Setup connections | 76 | // Setup connections |
| 76 | connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile())); | 77 | connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile())); |
| 78 | connect(ui.action_Load_Symbol_Map, SIGNAL(triggered()), this, SLOT(OnMenuLoadSymbolMap())); | ||
| 77 | connect(ui.action_Start, SIGNAL(triggered()), this, SLOT(OnStartGame())); | 79 | connect(ui.action_Start, SIGNAL(triggered()), this, SLOT(OnStartGame())); |
| 78 | connect(ui.action_Pause, SIGNAL(triggered()), this, SLOT(OnPauseGame())); | 80 | connect(ui.action_Pause, SIGNAL(triggered()), this, SLOT(OnPauseGame())); |
| 79 | connect(ui.action_Stop, SIGNAL(triggered()), this, SLOT(OnStopGame())); | 81 | connect(ui.action_Stop, SIGNAL(triggered()), this, SLOT(OnStopGame())); |
| @@ -140,11 +142,17 @@ void GMainWindow::BootGame(const char* filename) | |||
| 140 | 142 | ||
| 141 | void GMainWindow::OnMenuLoadFile() | 143 | void GMainWindow::OnMenuLoadFile() |
| 142 | { | 144 | { |
| 143 | QString filename = QFileDialog::getOpenFileName(this, tr("Load file"), QString(), tr("3DS homebrew (*.elf *.dat)")); | 145 | QString filename = QFileDialog::getOpenFileName(this, tr("Load file"), QString(), tr("3DS homebrew (*.elf *.dat *.bin)")); |
| 144 | if (filename.size()) | 146 | if (filename.size()) |
| 145 | BootGame(filename.toLatin1().data()); | 147 | BootGame(filename.toLatin1().data()); |
| 146 | } | 148 | } |
| 147 | 149 | ||
| 150 | void GMainWindow::OnMenuLoadSymbolMap() { | ||
| 151 | QString filename = QFileDialog::getOpenFileName(this, tr("Load symbol map"), QString(), tr("Symbol map (*)")); | ||
| 152 | if (filename.size()) | ||
| 153 | LoadSymbolMap(filename.toLatin1().data()); | ||
| 154 | } | ||
| 155 | |||
| 148 | void GMainWindow::OnStartGame() | 156 | void GMainWindow::OnStartGame() |
| 149 | { | 157 | { |
| 150 | render_window->GetEmuThread().SetCpuRunning(true); | 158 | render_window->GetEmuThread().SetCpuRunning(true); |
diff --git a/src/citra_qt/main.hxx b/src/citra_qt/main.hxx index b4b1c533c..fa122f76e 100644 --- a/src/citra_qt/main.hxx +++ b/src/citra_qt/main.hxx | |||
| @@ -33,10 +33,11 @@ private: | |||
| 33 | void closeEvent(QCloseEvent* event); | 33 | void closeEvent(QCloseEvent* event); |
| 34 | 34 | ||
| 35 | private slots: | 35 | private slots: |
| 36 | void OnStartGame(); | 36 | void OnStartGame(); |
| 37 | void OnPauseGame(); | 37 | void OnPauseGame(); |
| 38 | void OnStopGame(); | 38 | void OnStopGame(); |
| 39 | void OnMenuLoadFile(); | 39 | void OnMenuLoadFile(); |
| 40 | void OnMenuLoadSymbolMap(); | ||
| 40 | void OnOpenHotkeysDialog(); | 41 | void OnOpenHotkeysDialog(); |
| 41 | void OnConfigure(); | 42 | void OnConfigure(); |
| 42 | void ToggleWindowMode(); | 43 | void ToggleWindowMode(); |
diff --git a/src/citra_qt/main.ui b/src/citra_qt/main.ui index c0cb11a10..f3596716f 100644 --- a/src/citra_qt/main.ui +++ b/src/citra_qt/main.ui | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | <string>&File</string> | 40 | <string>&File</string> |
| 41 | </property> | 41 | </property> |
| 42 | <addaction name="action_Load_File"/> | 42 | <addaction name="action_Load_File"/> |
| 43 | <addaction name="action_Load_Symbol_Map"/> | ||
| 43 | <addaction name="separator"/> | 44 | <addaction name="separator"/> |
| 44 | <addaction name="action_Exit"/> | 45 | <addaction name="action_Exit"/> |
| 45 | </widget> | 46 | </widget> |
| @@ -72,12 +73,17 @@ | |||
| 72 | <addaction name="menu_Help"/> | 73 | <addaction name="menu_Help"/> |
| 73 | </widget> | 74 | </widget> |
| 74 | <widget class="QStatusBar" name="statusbar"/> | 75 | <widget class="QStatusBar" name="statusbar"/> |
| 75 | <action name="action_Load_File"> | 76 | <action name="action_Load_File"> |
| 76 | <property name="text"> | 77 | <property name="text"> |
| 77 | <string>Load file...</string> | 78 | <string>Load file...</string> |
| 78 | </property> | 79 | </property> |
| 79 | </action> | 80 | </action> |
| 80 | <action name="action_Exit"> | 81 | <action name="action_Load_Symbol_Map"> |
| 82 | <property name="text"> | ||
| 83 | <string>Load symbol map...</string> | ||
| 84 | </property> | ||
| 85 | </action> | ||
| 86 | <action name="action_Exit"> | ||
| 81 | <property name="text"> | 87 | <property name="text"> |
| 82 | <string>E&xit</string> | 88 | <string>E&xit</string> |
| 83 | </property> | 89 | </property> |
diff --git a/src/citra_qt/ui_main.h b/src/citra_qt/ui_main.h index cd3906ecc..04979e5ab 100644 --- a/src/citra_qt/ui_main.h +++ b/src/citra_qt/ui_main.h | |||
| @@ -27,6 +27,7 @@ class Ui_MainWindow | |||
| 27 | { | 27 | { |
| 28 | public: | 28 | public: |
| 29 | QAction *action_Load_File; | 29 | QAction *action_Load_File; |
| 30 | QAction *action_Load_Symbol_Map; | ||
| 30 | QAction *action_Exit; | 31 | QAction *action_Exit; |
| 31 | QAction *action_Start; | 32 | QAction *action_Start; |
| 32 | QAction *action_Pause; | 33 | QAction *action_Pause; |
| @@ -56,6 +57,8 @@ public: | |||
| 56 | MainWindow->setDockNestingEnabled(true); | 57 | MainWindow->setDockNestingEnabled(true); |
| 57 | action_Load_File = new QAction(MainWindow); | 58 | action_Load_File = new QAction(MainWindow); |
| 58 | action_Load_File->setObjectName(QString::fromUtf8("action_Load_File")); | 59 | action_Load_File->setObjectName(QString::fromUtf8("action_Load_File")); |
| 60 | action_Load_Symbol_Map = new QAction(MainWindow); | ||
| 61 | action_Load_Symbol_Map->setObjectName(QString::fromUtf8("action_Load_Symbol_Map")); | ||
| 59 | action_Exit = new QAction(MainWindow); | 62 | action_Exit = new QAction(MainWindow); |
| 60 | action_Exit->setObjectName(QString::fromUtf8("action_Exit")); | 63 | action_Exit->setObjectName(QString::fromUtf8("action_Exit")); |
| 61 | action_Start = new QAction(MainWindow); | 64 | action_Start = new QAction(MainWindow); |
| @@ -101,6 +104,7 @@ public: | |||
| 101 | menubar->addAction(menu_View->menuAction()); | 104 | menubar->addAction(menu_View->menuAction()); |
| 102 | menubar->addAction(menu_Help->menuAction()); | 105 | menubar->addAction(menu_Help->menuAction()); |
| 103 | menu_File->addAction(action_Load_File); | 106 | menu_File->addAction(action_Load_File); |
| 107 | menu_File->addAction(action_Load_Symbol_Map); | ||
| 104 | menu_File->addSeparator(); | 108 | menu_File->addSeparator(); |
| 105 | menu_File->addAction(action_Exit); | 109 | menu_File->addAction(action_Exit); |
| 106 | menu_Emulation->addAction(action_Start); | 110 | menu_Emulation->addAction(action_Start); |
| @@ -123,6 +127,7 @@ public: | |||
| 123 | { | 127 | { |
| 124 | MainWindow->setWindowTitle(QApplication::translate("MainWindow", "Citra", 0, QApplication::UnicodeUTF8)); | 128 | MainWindow->setWindowTitle(QApplication::translate("MainWindow", "Citra", 0, QApplication::UnicodeUTF8)); |
| 125 | action_Load_File->setText(QApplication::translate("MainWindow", "Load file...", 0, QApplication::UnicodeUTF8)); | 129 | action_Load_File->setText(QApplication::translate("MainWindow", "Load file...", 0, QApplication::UnicodeUTF8)); |
| 130 | action_Load_Symbol_Map->setText(QApplication::translate("MainWindow", "Load symbol map...", 0, QApplication::UnicodeUTF8)); | ||
| 126 | action_Exit->setText(QApplication::translate("MainWindow", "E&xit", 0, QApplication::UnicodeUTF8)); | 131 | action_Exit->setText(QApplication::translate("MainWindow", "E&xit", 0, QApplication::UnicodeUTF8)); |
| 127 | action_Start->setText(QApplication::translate("MainWindow", "&Start", 0, QApplication::UnicodeUTF8)); | 132 | action_Start->setText(QApplication::translate("MainWindow", "&Start", 0, QApplication::UnicodeUTF8)); |
| 128 | action_Pause->setText(QApplication::translate("MainWindow", "&Pause", 0, QApplication::UnicodeUTF8)); | 133 | action_Pause->setText(QApplication::translate("MainWindow", "&Pause", 0, QApplication::UnicodeUTF8)); |
diff --git a/src/common/bit_field.h b/src/common/bit_field.h new file mode 100644 index 000000000..dfd00d198 --- /dev/null +++ b/src/common/bit_field.h | |||
| @@ -0,0 +1,172 @@ | |||
| 1 | // Licensed under GPLv2 | ||
| 2 | // Refer to the license.txt file included. | ||
| 3 | |||
| 4 | |||
| 5 | // Copyright 2014 Tony Wasserka | ||
| 6 | // All rights reserved. | ||
| 7 | // | ||
| 8 | // Redistribution and use in source and binary forms, with or without | ||
| 9 | // modification, are permitted provided that the following conditions are met: | ||
| 10 | // | ||
| 11 | // * Redistributions of source code must retain the above copyright | ||
| 12 | // notice, this list of conditions and the following disclaimer. | ||
| 13 | // * Redistributions in binary form must reproduce the above copyright | ||
| 14 | // notice, this list of conditions and the following disclaimer in the | ||
| 15 | // documentation and/or other materials provided with the distribution. | ||
| 16 | // * Neither the name of the owner nor the names of its contributors may | ||
| 17 | // be used to endorse or promote products derived from this software | ||
| 18 | // without specific prior written permission. | ||
| 19 | // | ||
| 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 31 | |||
| 32 | |||
| 33 | #pragma once | ||
| 34 | |||
| 35 | #include <limits> | ||
| 36 | #include <type_traits> | ||
| 37 | |||
| 38 | #include "common/common.h" | ||
| 39 | |||
| 40 | /* | ||
| 41 | * Abstract bitfield class | ||
| 42 | * | ||
| 43 | * Allows endianness-independent access to individual bitfields within some raw | ||
| 44 | * integer value. The assembly generated by this class is identical to the | ||
| 45 | * usage of raw bitfields, so it's a perfectly fine replacement. | ||
| 46 | * | ||
| 47 | * For BitField<X,Y,Z>, X is the distance of the bitfield to the LSB of the | ||
| 48 | * raw value, Y is the length in bits of the bitfield. Z is an integer type | ||
| 49 | * which determines the sign of the bitfield. Z must have the same size as the | ||
| 50 | * raw integer. | ||
| 51 | * | ||
| 52 | * | ||
| 53 | * General usage: | ||
| 54 | * | ||
| 55 | * Create a new union with the raw integer value as a member. | ||
| 56 | * Then for each bitfield you want to expose, add a BitField member | ||
| 57 | * in the union. The template parameters are the bit offset and the number | ||
| 58 | * of desired bits. | ||
| 59 | * | ||
| 60 | * Changes in the bitfield members will then get reflected in the raw integer | ||
| 61 | * value and vice-versa. | ||
| 62 | * | ||
| 63 | * | ||
| 64 | * Sample usage: | ||
| 65 | * | ||
| 66 | * union SomeRegister | ||
| 67 | * { | ||
| 68 | * u32 hex; | ||
| 69 | * | ||
| 70 | * BitField<0,7,u32> first_seven_bits; // unsigned | ||
| 71 | * BitField<7,8,32> next_eight_bits; // unsigned | ||
| 72 | * BitField<3,15,s32> some_signed_fields; // signed | ||
| 73 | * }; | ||
| 74 | * | ||
| 75 | * This is equivalent to the little-endian specific code: | ||
| 76 | * | ||
| 77 | * union SomeRegister | ||
| 78 | * { | ||
| 79 | * u32 hex; | ||
| 80 | * | ||
| 81 | * struct | ||
| 82 | * { | ||
| 83 | * u32 first_seven_bits : 7; | ||
| 84 | * u32 next_eight_bits : 8; | ||
| 85 | * }; | ||
| 86 | * struct | ||
| 87 | * { | ||
| 88 | * u32 : 3; // padding | ||
| 89 | * s32 some_signed_fields : 15; | ||
| 90 | * }; | ||
| 91 | * }; | ||
| 92 | * | ||
| 93 | * | ||
| 94 | * Caveats: | ||
| 95 | * | ||
| 96 | * 1) | ||
| 97 | * BitField provides automatic casting from and to the storage type where | ||
| 98 | * appropriate. However, when using non-typesafe functions like printf, an | ||
| 99 | * explicit cast must be performed on the BitField object to make sure it gets | ||
| 100 | * passed correctly, e.g.: | ||
| 101 | * printf("Value: %d", (s32)some_register.some_signed_fields); | ||
| 102 | * | ||
| 103 | * 2) | ||
| 104 | * Not really a caveat, but potentially irritating: This class is used in some | ||
| 105 | * packed structures that do not guarantee proper alignment. Therefore we have | ||
| 106 | * to use #pragma pack here not to pack the members of the class, but instead | ||
| 107 | * to break GCC's assumption that the members of the class are aligned on | ||
| 108 | * sizeof(StorageType). | ||
| 109 | * TODO(neobrain): Confirm that this is a proper fix and not just masking | ||
| 110 | * symptoms. | ||
| 111 | */ | ||
| 112 | #pragma pack(1) | ||
| 113 | template<std::size_t position, std::size_t bits, typename T> | ||
| 114 | struct BitField | ||
| 115 | { | ||
| 116 | private: | ||
| 117 | // This constructor might be considered ambiguous: | ||
| 118 | // Would it initialize the storage or just the bitfield? | ||
| 119 | // Hence, delete it. Use the assignment operator to set bitfield values! | ||
| 120 | BitField(T val) = delete; | ||
| 121 | |||
| 122 | public: | ||
| 123 | // Force default constructor to be created | ||
| 124 | // so that we can use this within unions | ||
| 125 | BitField() = default; | ||
| 126 | |||
| 127 | __forceinline BitField& operator=(T val) | ||
| 128 | { | ||
| 129 | storage = (storage & ~GetMask()) | ((val << position) & GetMask()); | ||
| 130 | return *this; | ||
| 131 | } | ||
| 132 | |||
| 133 | __forceinline operator T() const | ||
| 134 | { | ||
| 135 | if (std::numeric_limits<T>::is_signed) | ||
| 136 | { | ||
| 137 | std::size_t shift = 8 * sizeof(T)-bits; | ||
| 138 | return (T)(((storage & GetMask()) << (shift - position)) >> shift); | ||
| 139 | } | ||
| 140 | else | ||
| 141 | { | ||
| 142 | return (T)((storage & GetMask()) >> position); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | private: | ||
| 147 | // StorageType is T for non-enum types and the underlying type of T if | ||
| 148 | // T is an enumeration. Note that T is wrapped within an enable_if in the | ||
| 149 | // former case to workaround compile errors which arise when using | ||
| 150 | // std::underlying_type<T>::type directly. | ||
| 151 | typedef typename std::conditional < std::is_enum<T>::value, | ||
| 152 | std::underlying_type<T>, | ||
| 153 | std::enable_if < true, T >> ::type::type StorageType; | ||
| 154 | |||
| 155 | // Unsigned version of StorageType | ||
| 156 | typedef typename std::make_unsigned<StorageType>::type StorageTypeU; | ||
| 157 | |||
| 158 | __forceinline StorageType GetMask() const | ||
| 159 | { | ||
| 160 | return ((~(StorageTypeU)0) >> (8 * sizeof(T)-bits)) << position; | ||
| 161 | } | ||
| 162 | |||
| 163 | StorageType storage; | ||
| 164 | |||
| 165 | static_assert(bits + position <= 8 * sizeof(T), "Bitfield out of range"); | ||
| 166 | |||
| 167 | // And, you know, just in case people specify something stupid like bits=position=0x80000000 | ||
| 168 | static_assert(position < 8 * sizeof(T), "Invalid position"); | ||
| 169 | static_assert(bits <= 8 * sizeof(T), "Invalid number of bits"); | ||
| 170 | static_assert(bits > 0, "Invalid number of bits"); | ||
| 171 | }; | ||
| 172 | #pragma pack() | ||
diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index 5048bebff..5dc6ff790 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj | |||
| @@ -157,6 +157,7 @@ | |||
| 157 | <ClInclude Include="atomic.h" /> | 157 | <ClInclude Include="atomic.h" /> |
| 158 | <ClInclude Include="atomic_gcc.h" /> | 158 | <ClInclude Include="atomic_gcc.h" /> |
| 159 | <ClInclude Include="atomic_win32.h" /> | 159 | <ClInclude Include="atomic_win32.h" /> |
| 160 | <ClInclude Include="bit_field.h" /> | ||
| 160 | <ClInclude Include="break_points.h" /> | 161 | <ClInclude Include="break_points.h" /> |
| 161 | <ClInclude Include="chunk_file.h" /> | 162 | <ClInclude Include="chunk_file.h" /> |
| 162 | <ClInclude Include="common.h" /> | 163 | <ClInclude Include="common.h" /> |
diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters index e9ea40022..268730228 100644 --- a/src/common/common.vcxproj.filters +++ b/src/common/common.vcxproj.filters | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | <ClInclude Include="utf8.h" /> | 39 | <ClInclude Include="utf8.h" /> |
| 40 | <ClInclude Include="symbols.h" /> | 40 | <ClInclude Include="symbols.h" /> |
| 41 | <ClInclude Include="scm_rev.h" /> | 41 | <ClInclude Include="scm_rev.h" /> |
| 42 | <ClInclude Include="bit_field.h" /> | ||
| 42 | </ItemGroup> | 43 | </ItemGroup> |
| 43 | <ItemGroup> | 44 | <ItemGroup> |
| 44 | <ClCompile Include="break_points.cpp" /> | 45 | <ClCompile Include="break_points.cpp" /> |
diff --git a/src/common/log.h b/src/common/log.h index 02db8bd55..d95f51f56 100644 --- a/src/common/log.h +++ b/src/common/log.h | |||
| @@ -33,7 +33,7 @@ enum LOG_TYPE { | |||
| 33 | EXPANSIONINTERFACE, | 33 | EXPANSIONINTERFACE, |
| 34 | GDB_STUB, | 34 | GDB_STUB, |
| 35 | ARM11, | 35 | ARM11, |
| 36 | GPFIFO, | 36 | GSP, |
| 37 | OSHLE, | 37 | OSHLE, |
| 38 | MASTER_LOG, | 38 | MASTER_LOG, |
| 39 | MEMMAP, | 39 | MEMMAP, |
| @@ -54,7 +54,7 @@ enum LOG_TYPE { | |||
| 54 | WII_IPC_FILEIO, | 54 | WII_IPC_FILEIO, |
| 55 | WII_IPC_HID, | 55 | WII_IPC_HID, |
| 56 | WII_IPC_HLE, | 56 | WII_IPC_HLE, |
| 57 | WII_IPC_NET, | 57 | SVC, |
| 58 | NDMA, | 58 | NDMA, |
| 59 | HLE, | 59 | HLE, |
| 60 | RENDER, | 60 | RENDER, |
diff --git a/src/common/log_manager.cpp b/src/common/log_manager.cpp index 8e56deb8f..80fd473b9 100644 --- a/src/common/log_manager.cpp +++ b/src/common/log_manager.cpp | |||
| @@ -42,7 +42,7 @@ LogManager::LogManager() | |||
| 42 | m_Log[LogTypes::STREAMINGINTERFACE] = new LogContainer("Stream", "StreamingInt"); | 42 | m_Log[LogTypes::STREAMINGINTERFACE] = new LogContainer("Stream", "StreamingInt"); |
| 43 | m_Log[LogTypes::DSPINTERFACE] = new LogContainer("DSP", "DSPInterface"); | 43 | m_Log[LogTypes::DSPINTERFACE] = new LogContainer("DSP", "DSPInterface"); |
| 44 | m_Log[LogTypes::DVDINTERFACE] = new LogContainer("DVD", "DVDInterface"); | 44 | m_Log[LogTypes::DVDINTERFACE] = new LogContainer("DVD", "DVDInterface"); |
| 45 | m_Log[LogTypes::GPFIFO] = new LogContainer("GP", "GPFifo"); | 45 | m_Log[LogTypes::GSP] = new LogContainer("GSP", "GSP"); |
| 46 | m_Log[LogTypes::EXPANSIONINTERFACE] = new LogContainer("EXI", "ExpansionInt"); | 46 | m_Log[LogTypes::EXPANSIONINTERFACE] = new LogContainer("EXI", "ExpansionInt"); |
| 47 | m_Log[LogTypes::GDB_STUB] = new LogContainer("GDB_STUB", "GDB Stub"); | 47 | m_Log[LogTypes::GDB_STUB] = new LogContainer("GDB_STUB", "GDB Stub"); |
| 48 | m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt"); | 48 | m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt"); |
| @@ -66,7 +66,7 @@ LogManager::LogManager() | |||
| 66 | m_Log[LogTypes::WII_IPC_FILEIO] = new LogContainer("WII_IPC_FILEIO", "WII IPC FILEIO"); | 66 | m_Log[LogTypes::WII_IPC_FILEIO] = new LogContainer("WII_IPC_FILEIO", "WII IPC FILEIO"); |
| 67 | m_Log[LogTypes::RENDER] = new LogContainer("RENDER", "RENDER"); | 67 | m_Log[LogTypes::RENDER] = new LogContainer("RENDER", "RENDER"); |
| 68 | m_Log[LogTypes::LCD] = new LogContainer("LCD", "LCD"); | 68 | m_Log[LogTypes::LCD] = new LogContainer("LCD", "LCD"); |
| 69 | m_Log[LogTypes::WII_IPC_NET] = new LogContainer("WII_IPC_NET", "WII IPC NET"); | 69 | m_Log[LogTypes::SVC] = new LogContainer("SVC", "Supervisor Call"); |
| 70 | m_Log[LogTypes::NDMA] = new LogContainer("NDMA", "NDMA"); | 70 | m_Log[LogTypes::NDMA] = new LogContainer("NDMA", "NDMA"); |
| 71 | m_Log[LogTypes::HLE] = new LogContainer("HLE", "High Level Emulation"); | 71 | m_Log[LogTypes::HLE] = new LogContainer("HLE", "High Level Emulation"); |
| 72 | m_Log[LogTypes::HW] = new LogContainer("HW", "Hardware"); | 72 | m_Log[LogTypes::HW] = new LogContainer("HW", "Hardware"); |
| @@ -147,7 +147,7 @@ LogContainer::LogContainer(const char* shortName, const char* fullName, bool ena | |||
| 147 | { | 147 | { |
| 148 | strncpy(m_fullName, fullName, 128); | 148 | strncpy(m_fullName, fullName, 128); |
| 149 | strncpy(m_shortName, shortName, 32); | 149 | strncpy(m_shortName, shortName, 32); |
| 150 | m_level = LogTypes::LWARNING; | 150 | m_level = (LogTypes::LOG_LEVELS)MAX_LOGLEVEL; |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | // LogContainer | 153 | // LogContainer |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 314f6e64c..eb4fef381 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -5,6 +5,7 @@ set(SRCS core.cpp | |||
| 5 | mem_map_funcs.cpp | 5 | mem_map_funcs.cpp |
| 6 | system.cpp | 6 | system.cpp |
| 7 | arm/disassembler/arm_disasm.cpp | 7 | arm/disassembler/arm_disasm.cpp |
| 8 | arm/disassembler/load_symbol_map.cpp | ||
| 8 | arm/interpreter/arm_interpreter.cpp | 9 | arm/interpreter/arm_interpreter.cpp |
| 9 | arm/interpreter/armemu.cpp | 10 | arm/interpreter/armemu.cpp |
| 10 | arm/interpreter/arminit.cpp | 11 | arm/interpreter/arminit.cpp |
| @@ -18,7 +19,8 @@ set(SRCS core.cpp | |||
| 18 | file_sys/directory_file_system.cpp | 19 | file_sys/directory_file_system.cpp |
| 19 | file_sys/meta_file_system.cpp | 20 | file_sys/meta_file_system.cpp |
| 20 | hle/hle.cpp | 21 | hle/hle.cpp |
| 21 | hle/mrc.cpp | 22 | hle/config_mem.cpp |
| 23 | hle/coprocessor.cpp | ||
| 22 | hle/syscall.cpp | 24 | hle/syscall.cpp |
| 23 | hle/service/apt.cpp | 25 | hle/service/apt.cpp |
| 24 | hle/service/gsp.cpp | 26 | hle/service/gsp.cpp |
diff --git a/src/core/arm/disassembler/load_symbol_map.cpp b/src/core/arm/disassembler/load_symbol_map.cpp new file mode 100644 index 000000000..d7fc0a042 --- /dev/null +++ b/src/core/arm/disassembler/load_symbol_map.cpp | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <string> | ||
| 6 | #include <vector> | ||
| 7 | |||
| 8 | #include "common/symbols.h" | ||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "common/file_util.h" | ||
| 11 | |||
| 12 | #include "core/arm/disassembler/load_symbol_map.h" | ||
| 13 | |||
| 14 | /* | ||
| 15 | * Loads a symbol map file for use with the disassembler | ||
| 16 | * @param filename String filename path of symbol map file | ||
| 17 | */ | ||
| 18 | void LoadSymbolMap(std::string filename) { | ||
| 19 | std::ifstream infile(filename); | ||
| 20 | |||
| 21 | std::string address_str, function_name, line; | ||
| 22 | u32 size, address; | ||
| 23 | |||
| 24 | while (std::getline(infile, line)) { | ||
| 25 | std::istringstream iss(line); | ||
| 26 | if (!(iss >> address_str >> size >> function_name)) { | ||
| 27 | break; // Error parsing | ||
| 28 | } | ||
| 29 | u32 address = std::stoul(address_str, nullptr, 16); | ||
| 30 | |||
| 31 | Symbols::Add(address, function_name, size, 2); | ||
| 32 | } | ||
| 33 | } | ||
diff --git a/src/core/arm/disassembler/load_symbol_map.h b/src/core/arm/disassembler/load_symbol_map.h new file mode 100644 index 000000000..837cca99b --- /dev/null +++ b/src/core/arm/disassembler/load_symbol_map.h | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <string> | ||
| 8 | |||
| 9 | /* | ||
| 10 | * Loads a symbol map file for use with the disassembler | ||
| 11 | * @param filename String filename path of symbol map file | ||
| 12 | */ | ||
| 13 | void LoadSymbolMap(std::string filename); | ||
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index a35c5c8dc..1af684fe3 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp | |||
| @@ -5536,14 +5536,15 @@ Handle_Load_Double (ARMul_State * state, ARMword instr) | |||
| 5536 | addr = base; | 5536 | addr = base; |
| 5537 | 5537 | ||
| 5538 | /* The address must be aligned on a 8 byte boundary. */ | 5538 | /* The address must be aligned on a 8 byte boundary. */ |
| 5539 | if (addr & 0x7) { | 5539 | // FIX(Normatt): Disable strict alignment on LDRD/STRD |
| 5540 | #ifdef ABORTS | 5540 | // if (addr & 0x7) { |
| 5541 | ARMul_DATAABORT (addr); | 5541 | //#ifdef ABORTS |
| 5542 | #else | 5542 | // ARMul_DATAABORT (addr); |
| 5543 | ARMul_UndefInstr (state, instr); | 5543 | //#else |
| 5544 | #endif | 5544 | // ARMul_UndefInstr (state, instr); |
| 5545 | return; | 5545 | //#endif |
| 5546 | } | 5546 | // return; |
| 5547 | // } | ||
| 5547 | 5548 | ||
| 5548 | /* For pre indexed or post indexed addressing modes, | 5549 | /* For pre indexed or post indexed addressing modes, |
| 5549 | check that the destination registers do not overlap | 5550 | check that the destination registers do not overlap |
| @@ -5640,14 +5641,15 @@ Handle_Store_Double (ARMul_State * state, ARMword instr) | |||
| 5640 | addr = base; | 5641 | addr = base; |
| 5641 | 5642 | ||
| 5642 | /* The address must be aligned on a 8 byte boundary. */ | 5643 | /* The address must be aligned on a 8 byte boundary. */ |
| 5643 | if (addr & 0x7) { | 5644 | // FIX(Normatt): Disable strict alignment on LDRD/STRD |
| 5644 | #ifdef ABORTS | 5645 | // if (addr & 0x7) { |
| 5645 | ARMul_DATAABORT (addr); | 5646 | //#ifdef ABORTS |
| 5646 | #else | 5647 | // ARMul_DATAABORT (addr); |
| 5647 | ARMul_UndefInstr (state, instr); | 5648 | //#else |
| 5648 | #endif | 5649 | // ARMul_UndefInstr (state, instr); |
| 5649 | return; | 5650 | //#endif |
| 5650 | } | 5651 | // return; |
| 5652 | // } | ||
| 5651 | 5653 | ||
| 5652 | /* For pre indexed or post indexed addressing modes, | 5654 | /* For pre indexed or post indexed addressing modes, |
| 5653 | check that the destination registers do not overlap | 5655 | check that the destination registers do not overlap |
| @@ -6405,6 +6407,8 @@ handle_v6_insn (ARMul_State * state, ARMword instr) | |||
| 6405 | if (state->Aborted) { | 6407 | if (state->Aborted) { |
| 6406 | TAKEABORT; | 6408 | TAKEABORT; |
| 6407 | } | 6409 | } |
| 6410 | // FIX(Normmatt): Handle RD in STREX/STREXB | ||
| 6411 | state->Reg[DESTReg] = 0; //Always succeed | ||
| 6408 | 6412 | ||
| 6409 | return 1; | 6413 | return 1; |
| 6410 | } | 6414 | } |
| @@ -6432,7 +6436,8 @@ handle_v6_insn (ARMul_State * state, ARMword instr) | |||
| 6432 | if (state->Aborted) { | 6436 | if (state->Aborted) { |
| 6433 | TAKEABORT; | 6437 | TAKEABORT; |
| 6434 | } | 6438 | } |
| 6435 | 6439 | // FIX(Normmatt): Handle RD in STREX/STREXB | |
| 6440 | state->Reg[DESTReg] = 0; //Always succeed | ||
| 6436 | //printf("In %s, strexb not implemented\n", __FUNCTION__); | 6441 | //printf("In %s, strexb not implemented\n", __FUNCTION__); |
| 6437 | UNDEF_LSRBPC; | 6442 | UNDEF_LSRBPC; |
| 6438 | /* WRITESDEST (dest); */ | 6443 | /* WRITESDEST (dest); */ |
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp index b2bbedc18..e531dceda 100644 --- a/src/core/arm/interpreter/armsupp.cpp +++ b/src/core/arm/interpreter/armsupp.cpp | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | //#include "ansidecl.h" | 21 | //#include "ansidecl.h" |
| 22 | #include "skyeye_defs.h" | 22 | #include "skyeye_defs.h" |
| 23 | #include "core/hle/mrc.h" | 23 | #include "core/hle/coprocessor.h" |
| 24 | #include "core/arm/disassembler/arm_disasm.h" | 24 | #include "core/arm/disassembler/arm_disasm.h" |
| 25 | 25 | ||
| 26 | unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, | 26 | unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, |
| @@ -661,39 +661,40 @@ ARMul_STC (ARMul_State * state, ARMword instr, ARMword address) | |||
| 661 | void | 661 | void |
| 662 | ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) | 662 | ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) |
| 663 | { | 663 | { |
| 664 | unsigned cpab; | 664 | HLE::CallMCR(instr, source); |
| 665 | //unsigned cpab; | ||
| 665 | 666 | ||
| 666 | //printf("SKYEYE ARMul_MCR, CPnum is %x, source %x\n",CPNum, source); | 667 | ////printf("SKYEYE ARMul_MCR, CPnum is %x, source %x\n",CPNum, source); |
| 667 | if (!CP_ACCESS_ALLOWED (state, CPNum)) { | 668 | //if (!CP_ACCESS_ALLOWED (state, CPNum)) { |
| 668 | //chy 2004-07-19 should fix in the future ????!!!! | 669 | // //chy 2004-07-19 should fix in the future ????!!!! |
| 669 | //printf("SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x\n",CPNum, source); | 670 | // //printf("SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x\n",CPNum, source); |
| 670 | ARMul_UndefInstr (state, instr); | 671 | // ARMul_UndefInstr (state, instr); |
| 671 | return; | 672 | // return; |
| 672 | } | 673 | //} |
| 673 | 674 | ||
| 674 | cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source); | 675 | //cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source); |
| 675 | 676 | ||
| 676 | while (cpab == ARMul_BUSY) { | 677 | //while (cpab == ARMul_BUSY) { |
| 677 | ARMul_Icycles (state, 1, 0); | 678 | // ARMul_Icycles (state, 1, 0); |
| 678 | 679 | ||
| 679 | if (IntPending (state)) { | 680 | // if (IntPending (state)) { |
| 680 | cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, | 681 | // cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, |
| 681 | instr, 0); | 682 | // instr, 0); |
| 682 | return; | 683 | // return; |
| 683 | } | 684 | // } |
| 684 | else | 685 | // else |
| 685 | cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, | 686 | // cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, |
| 686 | source); | 687 | // source); |
| 687 | } | 688 | //} |
| 688 | 689 | ||
| 689 | if (cpab == ARMul_CANT) { | 690 | //if (cpab == ARMul_CANT) { |
| 690 | printf ("SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x\n", instr, CPNum, source); | 691 | // printf ("SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x\n", instr, CPNum, source); |
| 691 | ARMul_Abort (state, ARMul_UndefinedInstrV); | 692 | // ARMul_Abort (state, ARMul_UndefinedInstrV); |
| 692 | } | 693 | //} |
| 693 | else { | 694 | //else { |
| 694 | BUSUSEDINCPCN; | 695 | // BUSUSEDINCPCN; |
| 695 | ARMul_Ccycles (state, 1, 0); | 696 | // ARMul_Ccycles (state, 1, 0); |
| 696 | } | 697 | //} |
| 697 | } | 698 | } |
| 698 | 699 | ||
| 699 | /* This function does the Busy-Waiting for an MCRR instruction. */ | 700 | /* This function does the Busy-Waiting for an MCRR instruction. */ |
| @@ -739,7 +740,7 @@ ARMul_MRC (ARMul_State * state, ARMword instr) | |||
| 739 | { | 740 | { |
| 740 | unsigned cpab; | 741 | unsigned cpab; |
| 741 | 742 | ||
| 742 | ARMword result = HLE::CallMRC((HLE::ARM11_MRC_OPERATION)BITS(20, 27)); | 743 | ARMword result = HLE::CallMRC(instr); |
| 743 | 744 | ||
| 744 | ////printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr); | 745 | ////printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr); |
| 745 | //if (!CP_ACCESS_ALLOWED (state, CPNum)) { | 746 | //if (!CP_ACCESS_ALLOWED (state, CPNum)) { |
diff --git a/src/core/arm/mmu/arm1176jzf_s_mmu.cpp b/src/core/arm/mmu/arm1176jzf_s_mmu.cpp index 7e7fbfbfa..a32f076b9 100644 --- a/src/core/arm/mmu/arm1176jzf_s_mmu.cpp +++ b/src/core/arm/mmu/arm1176jzf_s_mmu.cpp | |||
| @@ -355,7 +355,7 @@ arm1176jzf_s_mmu_load_instr (ARMul_State *state, ARMword va, ARMword *instr) | |||
| 355 | 355 | ||
| 356 | static int debug_count = 0; /* used for debug */ | 356 | static int debug_count = 0; /* used for debug */ |
| 357 | 357 | ||
| 358 | DEBUG_LOG(ARM11, "va = %x\n", va); | 358 | //DEBUG_LOG(ARM11, "va = %x\n", va); |
| 359 | 359 | ||
| 360 | va = mmu_pid_va_map (va); | 360 | va = mmu_pid_va_map (va); |
| 361 | if (MMU_Enabled) { | 361 | if (MMU_Enabled) { |
| @@ -444,7 +444,7 @@ arm1176jzf_s_mmu_read (ARMul_State *state, ARMword va, ARMword *data, | |||
| 444 | ARMword perm; /* physical addr access permissions */ | 444 | ARMword perm; /* physical addr access permissions */ |
| 445 | int ap, sop; | 445 | int ap, sop; |
| 446 | 446 | ||
| 447 | DEBUG_LOG(ARM11, "va = %x\n", va); | 447 | //DEBUG_LOG(ARM11, "va = %x\n", va); |
| 448 | 448 | ||
| 449 | va = mmu_pid_va_map (va); | 449 | va = mmu_pid_va_map (va); |
| 450 | real_va = va; | 450 | real_va = va; |
| @@ -629,7 +629,7 @@ arm1176jzf_s_mmu_write (ARMul_State *state, ARMword va, ARMword data, | |||
| 629 | } | 629 | } |
| 630 | #endif | 630 | #endif |
| 631 | 631 | ||
| 632 | DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data); | 632 | //DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data); |
| 633 | va = mmu_pid_va_map (va); | 633 | va = mmu_pid_va_map (va); |
| 634 | real_va = va; | 634 | real_va = va; |
| 635 | 635 | ||
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index be8448969..b56661e48 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj | |||
| @@ -138,6 +138,7 @@ | |||
| 138 | </ItemGroup> | 138 | </ItemGroup> |
| 139 | <ItemGroup> | 139 | <ItemGroup> |
| 140 | <ClCompile Include="arm\disassembler\arm_disasm.cpp" /> | 140 | <ClCompile Include="arm\disassembler\arm_disasm.cpp" /> |
| 141 | <ClCompile Include="arm\disassembler\load_symbol_map.cpp" /> | ||
| 141 | <ClCompile Include="arm\interpreter\armemu.cpp" /> | 142 | <ClCompile Include="arm\interpreter\armemu.cpp" /> |
| 142 | <ClCompile Include="arm\interpreter\arminit.cpp" /> | 143 | <ClCompile Include="arm\interpreter\arminit.cpp" /> |
| 143 | <ClCompile Include="arm\interpreter\armmmu.cpp" /> | 144 | <ClCompile Include="arm\interpreter\armmmu.cpp" /> |
| @@ -152,8 +153,9 @@ | |||
| 152 | <ClCompile Include="elf\elf_reader.cpp" /> | 153 | <ClCompile Include="elf\elf_reader.cpp" /> |
| 153 | <ClCompile Include="file_sys\directory_file_system.cpp" /> | 154 | <ClCompile Include="file_sys\directory_file_system.cpp" /> |
| 154 | <ClCompile Include="file_sys\meta_file_system.cpp" /> | 155 | <ClCompile Include="file_sys\meta_file_system.cpp" /> |
| 156 | <ClCompile Include="hle\config_mem.cpp" /> | ||
| 157 | <ClCompile Include="hle\coprocessor.cpp" /> | ||
| 155 | <ClCompile Include="hle\hle.cpp" /> | 158 | <ClCompile Include="hle\hle.cpp" /> |
| 156 | <ClCompile Include="hle\mrc.cpp" /> | ||
| 157 | <ClCompile Include="hle\service\apt.cpp" /> | 159 | <ClCompile Include="hle\service\apt.cpp" /> |
| 158 | <ClCompile Include="hle\service\gsp.cpp" /> | 160 | <ClCompile Include="hle\service\gsp.cpp" /> |
| 159 | <ClCompile Include="hle\service\hid.cpp" /> | 161 | <ClCompile Include="hle\service\hid.cpp" /> |
| @@ -171,6 +173,7 @@ | |||
| 171 | <ItemGroup> | 173 | <ItemGroup> |
| 172 | <ClInclude Include="arm\arm_interface.h" /> | 174 | <ClInclude Include="arm\arm_interface.h" /> |
| 173 | <ClInclude Include="arm\disassembler\arm_disasm.h" /> | 175 | <ClInclude Include="arm\disassembler\arm_disasm.h" /> |
| 176 | <ClInclude Include="arm\disassembler\load_symbol_map.h" /> | ||
| 174 | <ClInclude Include="arm\interpreter\armcpu.h" /> | 177 | <ClInclude Include="arm\interpreter\armcpu.h" /> |
| 175 | <ClInclude Include="arm\interpreter\armdefs.h" /> | 178 | <ClInclude Include="arm\interpreter\armdefs.h" /> |
| 176 | <ClInclude Include="arm\interpreter\armemu.h" /> | 179 | <ClInclude Include="arm\interpreter\armemu.h" /> |
| @@ -191,9 +194,10 @@ | |||
| 191 | <ClInclude Include="file_sys\directory_file_system.h" /> | 194 | <ClInclude Include="file_sys\directory_file_system.h" /> |
| 192 | <ClInclude Include="file_sys\file_sys.h" /> | 195 | <ClInclude Include="file_sys\file_sys.h" /> |
| 193 | <ClInclude Include="file_sys\meta_file_system.h" /> | 196 | <ClInclude Include="file_sys\meta_file_system.h" /> |
| 197 | <ClInclude Include="hle\config_mem.h" /> | ||
| 198 | <ClInclude Include="hle\coprocessor.h" /> | ||
| 194 | <ClInclude Include="hle\function_wrappers.h" /> | 199 | <ClInclude Include="hle\function_wrappers.h" /> |
| 195 | <ClInclude Include="hle\hle.h" /> | 200 | <ClInclude Include="hle\hle.h" /> |
| 196 | <ClInclude Include="hle\mrc.h" /> | ||
| 197 | <ClInclude Include="hle\service\apt.h" /> | 201 | <ClInclude Include="hle\service\apt.h" /> |
| 198 | <ClInclude Include="hle\service\gsp.h" /> | 202 | <ClInclude Include="hle\service\gsp.h" /> |
| 199 | <ClInclude Include="hle\service\hid.h" /> | 203 | <ClInclude Include="hle\service\hid.h" /> |
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index b5473bc41..5c947ec23 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters | |||
| @@ -105,7 +105,13 @@ | |||
| 105 | <ClCompile Include="hw\lcd.cpp"> | 105 | <ClCompile Include="hw\lcd.cpp"> |
| 106 | <Filter>hw</Filter> | 106 | <Filter>hw</Filter> |
| 107 | </ClCompile> | 107 | </ClCompile> |
| 108 | <ClCompile Include="hle\mrc.cpp"> | 108 | <ClCompile Include="arm\disassembler\load_symbol_map.cpp"> |
| 109 | <Filter>arm\disassembler</Filter> | ||
| 110 | </ClCompile> | ||
| 111 | <ClCompile Include="hle\coprocessor.cpp"> | ||
| 112 | <Filter>hle</Filter> | ||
| 113 | </ClCompile> | ||
| 114 | <ClCompile Include="hle\config_mem.cpp"> | ||
| 109 | <Filter>hle</Filter> | 115 | <Filter>hle</Filter> |
| 110 | </ClCompile> | 116 | </ClCompile> |
| 111 | </ItemGroup> | 117 | </ItemGroup> |
| @@ -208,7 +214,13 @@ | |||
| 208 | <ClInclude Include="hw\lcd.h"> | 214 | <ClInclude Include="hw\lcd.h"> |
| 209 | <Filter>hw</Filter> | 215 | <Filter>hw</Filter> |
| 210 | </ClInclude> | 216 | </ClInclude> |
| 211 | <ClInclude Include="hle\mrc.h"> | 217 | <ClInclude Include="arm\disassembler\load_symbol_map.h"> |
| 218 | <Filter>arm\disassembler</Filter> | ||
| 219 | </ClInclude> | ||
| 220 | <ClInclude Include="hle\coprocessor.h"> | ||
| 221 | <Filter>hle</Filter> | ||
| 222 | </ClInclude> | ||
| 223 | <ClInclude Include="hle\config_mem.h"> | ||
| 212 | <Filter>hle</Filter> | 224 | <Filter>hle</Filter> |
| 213 | </ClInclude> | 225 | </ClInclude> |
| 214 | </ItemGroup> | 226 | </ItemGroup> |
diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp new file mode 100644 index 000000000..48aa878cc --- /dev/null +++ b/src/core/hle/config_mem.cpp | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/common_types.h" | ||
| 6 | #include "common/log.h" | ||
| 7 | |||
| 8 | #include "core/hle/config_mem.h" | ||
| 9 | |||
| 10 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 11 | |||
| 12 | namespace ConfigMem { | ||
| 13 | |||
| 14 | enum { | ||
| 15 | KERNEL_VERSIONREVISION = 0x1FF80001, | ||
| 16 | KERNEL_VERSIONMINOR = 0x1FF80002, | ||
| 17 | KERNEL_VERSIONMAJOR = 0x1FF80003, | ||
| 18 | UPDATEFLAG = 0x1FF80004, | ||
| 19 | NSTID = 0x1FF80008, | ||
| 20 | SYSCOREVER = 0x1FF80010, | ||
| 21 | UNITINFO = 0x1FF80014, | ||
| 22 | KERNEL_CTRSDKVERSION = 0x1FF80018, | ||
| 23 | APPMEMTYPE = 0x1FF80030, | ||
| 24 | APPMEMALLOC = 0x1FF80040, | ||
| 25 | FIRM_VERSIONREVISION = 0x1FF80061, | ||
| 26 | FIRM_VERSIONMINOR = 0x1FF80062, | ||
| 27 | FIRM_VERSIONMAJOR = 0x1FF80063, | ||
| 28 | FIRM_SYSCOREVER = 0x1FF80064, | ||
| 29 | FIRM_CTRSDKVERSION = 0x1FF80068, | ||
| 30 | }; | ||
| 31 | |||
| 32 | template <typename T> | ||
| 33 | inline void Read(T &var, const u32 addr) { | ||
| 34 | switch (addr) { | ||
| 35 | |||
| 36 | // Bit 0 set for Retail | ||
| 37 | case UNITINFO: | ||
| 38 | var = 0x00000001; | ||
| 39 | break; | ||
| 40 | |||
| 41 | // Set app memory size to 64MB? | ||
| 42 | case APPMEMALLOC: | ||
| 43 | var = 0x04000000; | ||
| 44 | break; | ||
| 45 | |||
| 46 | // Unknown - normally set to: 0x08000000 - (APPMEMALLOC + *0x1FF80048) | ||
| 47 | // (Total FCRAM size - APPMEMALLOC - *0x1FF80048) | ||
| 48 | case 0x1FF80044: | ||
| 49 | var = 0x08000000 - (0x04000000 + 0x1400000); | ||
| 50 | break; | ||
| 51 | |||
| 52 | // Unknown - normally set to: 0x1400000 (20MB) | ||
| 53 | case 0x1FF80048: | ||
| 54 | var = 0x1400000; | ||
| 55 | break; | ||
| 56 | |||
| 57 | default: | ||
| 58 | ERROR_LOG(HLE, "unknown ConfigMem::Read%d @ 0x%08X", sizeof(var) * 8, addr); | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | // Explicitly instantiate template functions because we aren't defining this in the header: | ||
| 63 | |||
| 64 | template void Read<u64>(u64 &var, const u32 addr); | ||
| 65 | template void Read<u32>(u32 &var, const u32 addr); | ||
| 66 | template void Read<u16>(u16 &var, const u32 addr); | ||
| 67 | template void Read<u8>(u8 &var, const u32 addr); | ||
| 68 | |||
| 69 | |||
| 70 | } // namespace | ||
diff --git a/src/core/hle/config_mem.h b/src/core/hle/config_mem.h new file mode 100644 index 000000000..da396a3e6 --- /dev/null +++ b/src/core/hle/config_mem.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | // Configuration memory stores various hardware/kernel configuration settings. This memory page is | ||
| 8 | // read-only for ARM11 processes. I'm guessing this would normally be written to by the firmware/ | ||
| 9 | // bootrom. Because we're not emulating this, and essentially just "stubbing" the functionality, I'm | ||
| 10 | // putting this as a subset of HLE for now. | ||
| 11 | |||
| 12 | #include "common/common_types.h" | ||
| 13 | |||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 15 | |||
| 16 | namespace ConfigMem { | ||
| 17 | |||
| 18 | template <typename T> | ||
| 19 | inline void Read(T &var, const u32 addr); | ||
| 20 | |||
| 21 | } // namespace | ||
diff --git a/src/core/hle/coprocessor.cpp b/src/core/hle/coprocessor.cpp new file mode 100644 index 000000000..74305331c --- /dev/null +++ b/src/core/hle/coprocessor.cpp | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/coprocessor.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/mem_map.h" | ||
| 8 | #include "core/core.h" | ||
| 9 | |||
| 10 | namespace HLE { | ||
| 11 | |||
| 12 | /// Data synchronization barrier | ||
| 13 | u32 DataSynchronizationBarrier() { | ||
| 14 | return 0; | ||
| 15 | } | ||
| 16 | |||
| 17 | /// Returns the coprocessor (in this case, syscore) command buffer pointer | ||
| 18 | Addr GetThreadCommandBuffer() { | ||
| 19 | // Called on insruction: mrc p15, 0, r0, c13, c0, 3 | ||
| 20 | return Memory::KERNEL_MEMORY_VADDR; | ||
| 21 | } | ||
| 22 | |||
| 23 | /// Call an MCR (move to coprocessor from ARM register) instruction in HLE | ||
| 24 | s32 CallMCR(u32 instruction, u32 value) { | ||
| 25 | CoprocessorOperation operation = (CoprocessorOperation)((instruction >> 20) & 0xFF); | ||
| 26 | ERROR_LOG(OSHLE, "unimplemented MCR instruction=0x%08X, operation=%02X, value=%08X", | ||
| 27 | instruction, operation, value); | ||
| 28 | return 0; | ||
| 29 | } | ||
| 30 | |||
| 31 | /// Call an MRC (move to ARM register from coprocessor) instruction in HLE | ||
| 32 | s32 CallMRC(u32 instruction) { | ||
| 33 | CoprocessorOperation operation = (CoprocessorOperation)((instruction >> 20) & 0xFF); | ||
| 34 | |||
| 35 | switch (operation) { | ||
| 36 | |||
| 37 | case DATA_SYNCHRONIZATION_BARRIER: | ||
| 38 | return DataSynchronizationBarrier(); | ||
| 39 | |||
| 40 | case CALL_GET_THREAD_COMMAND_BUFFER: | ||
| 41 | return GetThreadCommandBuffer(); | ||
| 42 | |||
| 43 | default: | ||
| 44 | ERROR_LOG(OSHLE, "unimplemented MRC instruction 0x%08X", instruction); | ||
| 45 | break; | ||
| 46 | } | ||
| 47 | return 0; | ||
| 48 | } | ||
| 49 | |||
| 50 | } // namespace | ||
diff --git a/src/core/hle/mrc.h b/src/core/hle/coprocessor.h index d6b9f162f..03822af13 100644 --- a/src/core/hle/mrc.h +++ b/src/core/hle/coprocessor.h | |||
| @@ -8,13 +8,16 @@ | |||
| 8 | 8 | ||
| 9 | namespace HLE { | 9 | namespace HLE { |
| 10 | 10 | ||
| 11 | /// MRC operations (ARM register from coprocessor), decoded as instr[20:27] | 11 | /// Coprocessor operations |
| 12 | enum ARM11_MRC_OPERATION { | 12 | enum CoprocessorOperation { |
| 13 | DATA_SYNCHRONIZATION_BARRIER = 0xE0, | 13 | DATA_SYNCHRONIZATION_BARRIER = 0xE0, |
| 14 | CALL_GET_THREAD_COMMAND_BUFFER = 0xE1, | 14 | CALL_GET_THREAD_COMMAND_BUFFER = 0xE1, |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | /// Call an MRC operation in HLE | 17 | /// Call an MCR (move to coprocessor from ARM register) instruction in HLE |
| 18 | u32 CallMRC(ARM11_MRC_OPERATION operation); | 18 | s32 CallMCR(u32 instruction, u32 value); |
| 19 | |||
| 20 | /// Call an MRC (move to ARM register from coprocessor) instruction in HLE | ||
| 21 | s32 CallMRC(u32 instruction); | ||
| 19 | 22 | ||
| 20 | } // namespace | 23 | } // namespace |
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 4897d3f28..18b01b14b 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h | |||
| @@ -158,8 +158,8 @@ template<int func(u32, u32, u32, u32, u32)> void WrapI_UUUUU() { | |||
| 158 | RETURN(retval); | 158 | RETURN(retval); |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | template<int func()> void WrapI_V() { | 161 | template<int func(void*)> void WrapI_V() { |
| 162 | int retval = func(); | 162 | u32 retval = func(Memory::GetPointer(PARAM(0))); |
| 163 | RETURN(retval); | 163 | RETURN(retval); |
| 164 | } | 164 | } |
| 165 | 165 | ||
| @@ -638,6 +638,10 @@ template<u32 func(const char *, const char *)> void WrapU_CC() { | |||
| 638 | RETURN(retval); | 638 | RETURN(retval); |
| 639 | } | 639 | } |
| 640 | 640 | ||
| 641 | template<void func(const char*)> void WrapV_C() { | ||
| 642 | func(Memory::GetCharPointer(PARAM(0))); | ||
| 643 | } | ||
| 644 | |||
| 641 | template<void func(const char *, int)> void WrapV_CI() { | 645 | template<void func(const char *, int)> void WrapV_CI() { |
| 642 | func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); | 646 | func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); |
| 643 | } | 647 | } |
| @@ -716,18 +720,28 @@ template <int func(int, const char *, int)> void WrapI_ICI() { | |||
| 716 | } | 720 | } |
| 717 | 721 | ||
| 718 | template<int func(int, void *, void *, void *, void *, u32, int)> void WrapI_IVVVVUI(){ | 722 | template<int func(int, void *, void *, void *, void *, u32, int)> void WrapI_IVVVVUI(){ |
| 719 | u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), Memory::GetPointer(PARAM(2)), Memory::GetPointer(PARAM(3)), Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) ); | 723 | u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), Memory::GetPointer(PARAM(2)), Memory::GetPointer(PARAM(3)), Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) ); |
| 720 | RETURN(retval); | 724 | RETURN(retval); |
| 721 | } | 725 | } |
| 722 | 726 | ||
| 723 | template<int func(int, const char *, u32, void *, int, int, int)> void WrapI_ICUVIII(){ | 727 | template<int func(int, const char *, u32, void *, int, int, int)> void WrapI_ICUVIII(){ |
| 724 | u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)), PARAM(4), PARAM(5), PARAM(6)); | 728 | u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)), PARAM(4), PARAM(5), PARAM(6)); |
| 725 | RETURN(retval); | 729 | RETURN(retval); |
| 726 | } | 730 | } |
| 727 | 731 | ||
| 728 | template<int func(void *, u32, u32, u32, u32, u32)> void WrapI_VUUUUU(){ | 732 | template<int func(void*, u32)> void WrapI_VU(){ |
| 729 | u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5)); | 733 | u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1)); |
| 730 | RETURN(retval); | 734 | RETURN(retval); |
| 735 | } | ||
| 736 | |||
| 737 | template<int func(void*, u32, void*, int)> void WrapI_VUVI(){ | ||
| 738 | u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), PARAM(3)); | ||
| 739 | RETURN(retval); | ||
| 740 | } | ||
| 741 | |||
| 742 | template<int func(void*, u32, u32, u32, u32, u32)> void WrapI_VUUUUU(){ | ||
| 743 | u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5)); | ||
| 744 | RETURN(retval); | ||
| 731 | } | 745 | } |
| 732 | 746 | ||
| 733 | template<int func(u32, s64)> void WrapI_US64() { | 747 | template<int func(u32, s64)> void WrapI_US64() { |
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index aae9a3943..be151665b 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp | |||
| @@ -15,49 +15,6 @@ namespace HLE { | |||
| 15 | 15 | ||
| 16 | static std::vector<ModuleDef> g_module_db; | 16 | static std::vector<ModuleDef> g_module_db; |
| 17 | 17 | ||
| 18 | u8* g_command_buffer = NULL; ///< Command buffer used for sharing between appcore and syscore | ||
| 19 | |||
| 20 | // Read from memory used by CTROS HLE functions | ||
| 21 | template <typename T> | ||
| 22 | inline void Read(T &var, const u32 addr) { | ||
| 23 | if (addr >= HLE::CMD_BUFFER_ADDR && addr < HLE::CMD_BUFFER_ADDR_END) { | ||
| 24 | var = *((const T*)&g_command_buffer[addr & CMD_BUFFER_MASK]); | ||
| 25 | } else { | ||
| 26 | ERROR_LOG(HLE, "unknown read from address %08X", addr); | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | // Write to memory used by CTROS HLE functions | ||
| 31 | template <typename T> | ||
| 32 | inline void Write(u32 addr, const T data) { | ||
| 33 | if (addr >= HLE::CMD_BUFFER_ADDR && addr < HLE::CMD_BUFFER_ADDR_END) { | ||
| 34 | *(T*)&g_command_buffer[addr & CMD_BUFFER_MASK] = data; | ||
| 35 | } else { | ||
| 36 | ERROR_LOG(HLE, "unknown write to address %08X", addr); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 40 | u8 *GetPointer(const u32 addr) { | ||
| 41 | if (addr >= HLE::CMD_BUFFER_ADDR && addr < HLE::CMD_BUFFER_ADDR_END) { | ||
| 42 | return g_command_buffer + (addr & CMD_BUFFER_MASK); | ||
| 43 | } else { | ||
| 44 | ERROR_LOG(HLE, "unknown pointer from address %08X", addr); | ||
| 45 | return 0; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | // Explicitly instantiate template functions because we aren't defining this in the header: | ||
| 50 | |||
| 51 | template void Read<u64>(u64 &var, const u32 addr); | ||
| 52 | template void Read<u32>(u32 &var, const u32 addr); | ||
| 53 | template void Read<u16>(u16 &var, const u32 addr); | ||
| 54 | template void Read<u8>(u8 &var, const u32 addr); | ||
| 55 | |||
| 56 | template void Write<u64>(u32 addr, const u64 data); | ||
| 57 | template void Write<u32>(u32 addr, const u32 data); | ||
| 58 | template void Write<u16>(u32 addr, const u16 data); | ||
| 59 | template void Write<u8>(u32 addr, const u8 data); | ||
| 60 | |||
| 61 | const FunctionDef* GetSyscallInfo(u32 opcode) { | 18 | const FunctionDef* GetSyscallInfo(u32 opcode) { |
| 62 | u32 func_num = opcode & 0xFFFFFF; // 8 bits | 19 | u32 func_num = opcode & 0xFFFFFF; // 8 bits |
| 63 | if (func_num > 0xFF) { | 20 | if (func_num > 0xFF) { |
| @@ -91,8 +48,6 @@ void RegisterAllModules() { | |||
| 91 | 48 | ||
| 92 | void Init() { | 49 | void Init() { |
| 93 | Service::Init(); | 50 | Service::Init(); |
| 94 | |||
| 95 | g_command_buffer = new u8[CMD_BUFFER_SIZE]; | ||
| 96 | 51 | ||
| 97 | RegisterAllModules(); | 52 | RegisterAllModules(); |
| 98 | 53 | ||
| @@ -102,8 +57,6 @@ void Init() { | |||
| 102 | void Shutdown() { | 57 | void Shutdown() { |
| 103 | Service::Shutdown(); | 58 | Service::Shutdown(); |
| 104 | 59 | ||
| 105 | delete g_command_buffer; | ||
| 106 | |||
| 107 | g_module_db.clear(); | 60 | g_module_db.clear(); |
| 108 | 61 | ||
| 109 | NOTICE_LOG(HLE, "shutdown OK"); | 62 | NOTICE_LOG(HLE, "shutdown OK"); |
diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h index 907e2d741..42f37e29c 100644 --- a/src/core/hle/hle.h +++ b/src/core/hle/hle.h | |||
| @@ -17,13 +17,6 @@ | |||
| 17 | 17 | ||
| 18 | namespace HLE { | 18 | namespace HLE { |
| 19 | 19 | ||
| 20 | enum { | ||
| 21 | CMD_BUFFER_ADDR = 0xA0010000, ///< Totally arbitrary unused address space | ||
| 22 | CMD_BUFFER_SIZE = 0x10000, | ||
| 23 | CMD_BUFFER_MASK = (CMD_BUFFER_SIZE - 1), | ||
| 24 | CMD_BUFFER_ADDR_END = (CMD_BUFFER_ADDR + CMD_BUFFER_SIZE), | ||
| 25 | }; | ||
| 26 | |||
| 27 | typedef u32 Addr; | 20 | typedef u32 Addr; |
| 28 | typedef void (*Func)(); | 21 | typedef void (*Func)(); |
| 29 | 22 | ||
| @@ -39,20 +32,6 @@ struct ModuleDef { | |||
| 39 | const FunctionDef* func_table; | 32 | const FunctionDef* func_table; |
| 40 | }; | 33 | }; |
| 41 | 34 | ||
| 42 | // Read from memory used by CTROS HLE functions | ||
| 43 | template <typename T> | ||
| 44 | inline void Read(T &var, const u32 addr); | ||
| 45 | |||
| 46 | // Write to memory used by CTROS HLE functions | ||
| 47 | template <typename T> | ||
| 48 | inline void Write(u32 addr, const T data); | ||
| 49 | |||
| 50 | u8* GetPointer(const u32 Address); | ||
| 51 | |||
| 52 | inline const char* GetCharPointer(const u32 address) { | ||
| 53 | return (const char *)GetPointer(address); | ||
| 54 | } | ||
| 55 | |||
| 56 | void RegisterModule(std::string name, int num_functions, const FunctionDef *func_table); | 35 | void RegisterModule(std::string name, int num_functions, const FunctionDef *func_table); |
| 57 | 36 | ||
| 58 | void CallSyscall(u32 opcode); | 37 | void CallSyscall(u32 opcode); |
diff --git a/src/core/hle/mrc.cpp b/src/core/hle/mrc.cpp deleted file mode 100644 index 5223be7c9..000000000 --- a/src/core/hle/mrc.cpp +++ /dev/null | |||
| @@ -1,64 +0,0 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/mrc.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/mem_map.h" | ||
| 8 | #include "core/core.h" | ||
| 9 | |||
| 10 | namespace HLE { | ||
| 11 | |||
| 12 | enum { | ||
| 13 | CMD_GX_REQUEST_DMA = 0x00000000, | ||
| 14 | }; | ||
| 15 | |||
| 16 | /// Data synchronization barrier | ||
| 17 | u32 DataSynchronizationBarrier(u32* command_buffer) { | ||
| 18 | u32 command = command_buffer[0]; | ||
| 19 | |||
| 20 | switch (command) { | ||
| 21 | |||
| 22 | case CMD_GX_REQUEST_DMA: | ||
| 23 | { | ||
| 24 | u32* src = (u32*)Memory::GetPointer(command_buffer[1]); | ||
| 25 | u32* dst = (u32*)Memory::GetPointer(command_buffer[2]); | ||
| 26 | u32 size = command_buffer[3]; | ||
| 27 | memcpy(dst, src, size); | ||
| 28 | } | ||
| 29 | break; | ||
| 30 | |||
| 31 | default: | ||
| 32 | ERROR_LOG(OSHLE, "MRC::DataSynchronizationBarrier unknown command 0x%08X", command); | ||
| 33 | return -1; | ||
| 34 | } | ||
| 35 | |||
| 36 | return 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | /// Returns the coprocessor (in this case, syscore) command buffer pointer | ||
| 40 | Addr GetThreadCommandBuffer() { | ||
| 41 | // Called on insruction: mrc p15, 0, r0, c13, c0, 3 | ||
| 42 | // Returns an address in OSHLE memory for the CPU to read/write to | ||
| 43 | RETURN(CMD_BUFFER_ADDR); | ||
| 44 | return CMD_BUFFER_ADDR; | ||
| 45 | } | ||
| 46 | |||
| 47 | /// Call an MRC operation in HLE | ||
| 48 | u32 CallMRC(ARM11_MRC_OPERATION operation) { | ||
| 49 | switch (operation) { | ||
| 50 | |||
| 51 | case DATA_SYNCHRONIZATION_BARRIER: | ||
| 52 | return DataSynchronizationBarrier((u32*)Memory::GetPointer(PARAM(0))); | ||
| 53 | |||
| 54 | case CALL_GET_THREAD_COMMAND_BUFFER: | ||
| 55 | return GetThreadCommandBuffer(); | ||
| 56 | |||
| 57 | default: | ||
| 58 | ERROR_LOG(OSHLE, "unimplemented MRC operation 0x%02X", operation); | ||
| 59 | break; | ||
| 60 | } | ||
| 61 | return -1; | ||
| 62 | } | ||
| 63 | |||
| 64 | } // namespace | ||
diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index 4a1e8c992..709ac5493 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp | |||
| @@ -18,7 +18,7 @@ void Initialize(Service::Interface* self) { | |||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | void GetLockHandle(Service::Interface* self) { | 20 | void GetLockHandle(Service::Interface* self) { |
| 21 | u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset); | 21 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 22 | cmd_buff[5] = 0x00000000; // TODO: This should be an actual mutex handle | 22 | cmd_buff[5] = 0x00000000; // TODO: This should be an actual mutex handle |
| 23 | } | 23 | } |
| 24 | 24 | ||
diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index 88c1f1a0f..12c7dabcd 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | #include "common/log.h" | 6 | #include "common/log.h" |
| 7 | #include "common/bit_field.h" | ||
| 7 | 8 | ||
| 8 | #include "core/mem_map.h" | 9 | #include "core/mem_map.h" |
| 9 | #include "core/hle/hle.h" | 10 | #include "core/hle/hle.h" |
| @@ -12,10 +13,51 @@ | |||
| 12 | #include "core/hw/lcd.h" | 13 | #include "core/hw/lcd.h" |
| 13 | 14 | ||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 15 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 16 | |||
| 17 | /// GSP shared memory GX command buffer header | ||
| 18 | union GX_CmdBufferHeader { | ||
| 19 | u32 hex; | ||
| 20 | |||
| 21 | // Current command index. This index is updated by GSP module after loading the command data, | ||
| 22 | // right before the command is processed. When this index is updated by GSP module, the total | ||
| 23 | // commands field is decreased by one as well. | ||
| 24 | BitField<0,8,u32> index; | ||
| 25 | |||
| 26 | // Total commands to process, must not be value 0 when GSP module handles commands. This must be | ||
| 27 | // <=15 when writing a command to shared memory. This is incremented by the application when | ||
| 28 | // writing a command to shared memory, after increasing this value TriggerCmdReqQueue is only | ||
| 29 | // used if this field is value 1. | ||
| 30 | BitField<8,8,u32> number_commands; | ||
| 31 | |||
| 32 | }; | ||
| 33 | |||
| 34 | /// Gets the address of the start (header) of a command buffer in GSP shared memory | ||
| 35 | static inline u32 GX_GetCmdBufferAddress(u32 thread_id) { | ||
| 36 | return (0x10002000 + 0x800 + (thread_id * 0x200)); | ||
| 37 | } | ||
| 38 | |||
| 39 | /// Gets a pointer to the start (header) of a command buffer in GSP shared memory | ||
| 40 | static inline u8* GX_GetCmdBufferPointer(u32 thread_id, u32 offset=0) { | ||
| 41 | return Memory::GetPointer(GX_GetCmdBufferAddress(thread_id) + offset); | ||
| 42 | } | ||
| 43 | |||
| 44 | /// Finishes execution of a GSP command | ||
| 45 | void GX_FinishCommand(u32 thread_id) { | ||
| 46 | GX_CmdBufferHeader* header = (GX_CmdBufferHeader*)GX_GetCmdBufferPointer(thread_id); | ||
| 47 | header->number_commands = header->number_commands - 1; | ||
| 48 | } | ||
| 49 | |||
| 50 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 15 | // Namespace GSP_GPU | 51 | // Namespace GSP_GPU |
| 16 | 52 | ||
| 17 | namespace GSP_GPU { | 53 | namespace GSP_GPU { |
| 18 | 54 | ||
| 55 | u32 g_thread_id = 0; | ||
| 56 | |||
| 57 | enum { | ||
| 58 | CMD_GX_REQUEST_DMA = 0x00000000, | ||
| 59 | }; | ||
| 60 | |||
| 19 | enum { | 61 | enum { |
| 20 | REG_FRAMEBUFFER_1 = 0x00400468, | 62 | REG_FRAMEBUFFER_1 = 0x00400468, |
| 21 | REG_FRAMEBUFFER_2 = 0x00400494, | 63 | REG_FRAMEBUFFER_2 = 0x00400494, |
| @@ -26,7 +68,7 @@ void ReadHWRegs(Service::Interface* self) { | |||
| 26 | static const u32 framebuffer_1[] = {LCD::PADDR_VRAM_TOP_LEFT_FRAME1, LCD::PADDR_VRAM_TOP_RIGHT_FRAME1}; | 68 | static const u32 framebuffer_1[] = {LCD::PADDR_VRAM_TOP_LEFT_FRAME1, LCD::PADDR_VRAM_TOP_RIGHT_FRAME1}; |
| 27 | static const u32 framebuffer_2[] = {LCD::PADDR_VRAM_TOP_LEFT_FRAME2, LCD::PADDR_VRAM_TOP_RIGHT_FRAME2}; | 69 | static const u32 framebuffer_2[] = {LCD::PADDR_VRAM_TOP_LEFT_FRAME2, LCD::PADDR_VRAM_TOP_RIGHT_FRAME2}; |
| 28 | 70 | ||
| 29 | u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset); | 71 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 30 | u32 reg_addr = cmd_buff[1]; | 72 | u32 reg_addr = cmd_buff[1]; |
| 31 | u32 size = cmd_buff[2]; | 73 | u32 size = cmd_buff[2]; |
| 32 | u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]); | 74 | u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]); |
| @@ -50,18 +92,37 @@ void ReadHWRegs(Service::Interface* self) { | |||
| 50 | break; | 92 | break; |
| 51 | 93 | ||
| 52 | default: | 94 | default: |
| 53 | ERROR_LOG(OSHLE, "GSP_GPU::ReadHWRegs unknown register read at address %08X", reg_addr); | 95 | ERROR_LOG(GSP, "ReadHWRegs unknown register read at address %08X", reg_addr); |
| 54 | } | 96 | } |
| 55 | 97 | ||
| 56 | } | 98 | } |
| 57 | 99 | ||
| 58 | void RegisterInterruptRelayQueue(Service::Interface* self) { | 100 | void RegisterInterruptRelayQueue(Service::Interface* self) { |
| 59 | u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset); | 101 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 60 | u32 flags = cmd_buff[1]; | 102 | u32 flags = cmd_buff[1]; |
| 61 | u32 event_handle = cmd_buff[3]; // TODO(bunnei): Implement event handling | 103 | u32 event_handle = cmd_buff[3]; // TODO(bunnei): Implement event handling |
| 104 | |||
| 105 | cmd_buff[2] = g_thread_id; // ThreadID | ||
| 62 | cmd_buff[4] = self->NewHandle(); | 106 | cmd_buff[4] = self->NewHandle(); |
| 107 | } | ||
| 108 | |||
| 109 | /// This triggers handling of the GX command written to the command buffer in shared memory. | ||
| 110 | void TriggerCmdReqQueue(Service::Interface* self) { | ||
| 111 | GX_CmdBufferHeader* header = (GX_CmdBufferHeader*)GX_GetCmdBufferPointer(g_thread_id); | ||
| 112 | u32* cmd_buff = (u32*)GX_GetCmdBufferPointer(g_thread_id, 0x20 + (header->index * 0x20)); | ||
| 63 | 113 | ||
| 64 | return; | 114 | switch (cmd_buff[0]) { |
| 115 | |||
| 116 | // GX request DMA - typically used for copying memory from GSP heap to VRAM | ||
| 117 | case CMD_GX_REQUEST_DMA: | ||
| 118 | memcpy(Memory::GetPointer(cmd_buff[2]), Memory::GetPointer(cmd_buff[1]), cmd_buff[3]); | ||
| 119 | break; | ||
| 120 | |||
| 121 | default: | ||
| 122 | ERROR_LOG(GSP, "TriggerCmdReqQueue unknown command 0x%08X", cmd_buff[0]); | ||
| 123 | } | ||
| 124 | |||
| 125 | GX_FinishCommand(g_thread_id); | ||
| 65 | } | 126 | } |
| 66 | 127 | ||
| 67 | const Interface::FunctionInfo FunctionTable[] = { | 128 | const Interface::FunctionInfo FunctionTable[] = { |
| @@ -76,7 +137,7 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 76 | {0x00090082, NULL, "InvalidateDataCache"}, | 137 | {0x00090082, NULL, "InvalidateDataCache"}, |
| 77 | {0x000A0044, NULL, "RegisterInterruptEvents"}, | 138 | {0x000A0044, NULL, "RegisterInterruptEvents"}, |
| 78 | {0x000B0040, NULL, "SetLcdForceBlack"}, | 139 | {0x000B0040, NULL, "SetLcdForceBlack"}, |
| 79 | {0x000C0000, NULL, "TriggerCmdReqQueue"}, | 140 | {0x000C0000, TriggerCmdReqQueue, "TriggerCmdReqQueue"}, |
| 80 | {0x000D0140, NULL, "SetDisplayTransfer"}, | 141 | {0x000D0140, NULL, "SetDisplayTransfer"}, |
| 81 | {0x000E0180, NULL, "SetTextureCopy"}, | 142 | {0x000E0180, NULL, "SetTextureCopy"}, |
| 82 | {0x000F0200, NULL, "SetMemoryFill"}, | 143 | {0x000F0200, NULL, "SetMemoryFill"}, |
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index b79dc9458..b260a290a 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | #include "common/common.h" | 11 | #include "common/common.h" |
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "core/mem_map.h" | ||
| 13 | #include "core/hle/syscall.h" | 14 | #include "core/hle/syscall.h" |
| 14 | 15 | ||
| 15 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 16 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -22,6 +23,15 @@ typedef s32 NativeUID; ///< Native handle for a service | |||
| 22 | static const int kMaxPortSize = 0x08; ///< Maximum size of a port name (8 characters) | 23 | static const int kMaxPortSize = 0x08; ///< Maximum size of a port name (8 characters) |
| 23 | static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of header | 24 | static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of header |
| 24 | 25 | ||
| 26 | /** | ||
| 27 | * Returns a pointer to the command buffer in kernel memory | ||
| 28 | * @param offset Optional offset into command buffer | ||
| 29 | * @return Pointer to command buffer | ||
| 30 | */ | ||
| 31 | inline static u32* GetCommandBuffer(const int offset=0) { | ||
| 32 | return (u32*)Memory::GetPointer(Memory::KERNEL_MEMORY_VADDR + kCommandHeaderOffset + offset); | ||
| 33 | } | ||
| 34 | |||
| 25 | class Manager; | 35 | class Manager; |
| 26 | 36 | ||
| 27 | /// Interface to a CTROS service | 37 | /// Interface to a CTROS service |
| @@ -81,7 +91,7 @@ public: | |||
| 81 | * @return Return result of svcSendSyncRequest passed back to user app | 91 | * @return Return result of svcSendSyncRequest passed back to user app |
| 82 | */ | 92 | */ |
| 83 | Syscall::Result Sync() { | 93 | Syscall::Result Sync() { |
| 84 | u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + kCommandHeaderOffset); | 94 | u32* cmd_buff = GetCommandBuffer(); |
| 85 | auto itr = m_functions.find(cmd_buff[0]); | 95 | auto itr = m_functions.find(cmd_buff[0]); |
| 86 | 96 | ||
| 87 | if (itr == m_functions.end()) { | 97 | if (itr == m_functions.end()) { |
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 9437868c5..071741444 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp | |||
| @@ -18,7 +18,7 @@ void Initialize(Service::Interface* self) { | |||
| 18 | 18 | ||
| 19 | void GetServiceHandle(Service::Interface* self) { | 19 | void GetServiceHandle(Service::Interface* self) { |
| 20 | Syscall::Result res = 0; | 20 | Syscall::Result res = 0; |
| 21 | u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset); | 21 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 22 | 22 | ||
| 23 | std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); | 23 | std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); |
| 24 | Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); | 24 | Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); |
diff --git a/src/core/hle/syscall.cpp b/src/core/hle/syscall.cpp index df6412743..d47df6038 100644 --- a/src/core/hle/syscall.cpp +++ b/src/core/hle/syscall.cpp | |||
| @@ -29,6 +29,9 @@ enum MapMemoryPermission { | |||
| 29 | Result ControlMemory(u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { | 29 | Result ControlMemory(u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { |
| 30 | u32 virtual_address = 0x00000000; | 30 | u32 virtual_address = 0x00000000; |
| 31 | 31 | ||
| 32 | DEBUG_LOG(SVC, "ControlMemory called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", | ||
| 33 | operation, addr0, addr1, size, permissions); | ||
| 34 | |||
| 32 | switch (operation) { | 35 | switch (operation) { |
| 33 | 36 | ||
| 34 | // Map normal heap memory | 37 | // Map normal heap memory |
| @@ -43,16 +46,18 @@ Result ControlMemory(u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissi | |||
| 43 | 46 | ||
| 44 | // Unknown ControlMemory operation | 47 | // Unknown ControlMemory operation |
| 45 | default: | 48 | default: |
| 46 | ERROR_LOG(OSHLE, "Unknown ControlMemory operation %08X", operation); | 49 | ERROR_LOG(SVC, "ControlMemory unknown operation=0x%08X", operation); |
| 47 | } | 50 | } |
| 48 | 51 | ||
| 49 | Core::g_app_core->SetReg(1, virtual_address); | 52 | Core::g_app_core->SetReg(1, virtual_address); |
| 53 | |||
| 50 | return 0; | 54 | return 0; |
| 51 | } | 55 | } |
| 52 | 56 | ||
| 53 | /// Maps a memory block to specified address | 57 | /// Maps a memory block to specified address |
| 54 | Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission) { | 58 | Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission) { |
| 55 | int x = 0; | 59 | DEBUG_LOG(SVC, "MapMemoryBlock called memblock=0x08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", |
| 60 | memblock, addr, mypermissions, otherpermission); | ||
| 56 | switch (mypermissions) { | 61 | switch (mypermissions) { |
| 57 | case MEMORY_PERMISSION_NORMAL: | 62 | case MEMORY_PERMISSION_NORMAL: |
| 58 | case MEMORY_PERMISSION_NORMAL + 1: | 63 | case MEMORY_PERMISSION_NORMAL + 1: |
| @@ -60,20 +65,23 @@ Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherper | |||
| 60 | Memory::MapBlock_Shared(memblock, addr, mypermissions); | 65 | Memory::MapBlock_Shared(memblock, addr, mypermissions); |
| 61 | break; | 66 | break; |
| 62 | default: | 67 | default: |
| 63 | ERROR_LOG(OSHLE, "Unknown MapMemoryBlock permissions %08X", mypermissions); | 68 | ERROR_LOG(OSHLE, "MapMemoryBlock unknown permissions=0x%08X", mypermissions); |
| 64 | } | 69 | } |
| 65 | return 0; | 70 | return 0; |
| 66 | } | 71 | } |
| 67 | 72 | ||
| 68 | /// Connect to an OS service given the port name, returns the handle to the port to out | 73 | /// Connect to an OS service given the port name, returns the handle to the port to out |
| 69 | Result ConnectToPort(void* out, const char* port_name) { | 74 | Result ConnectToPort(void* out, const char* port_name) { |
| 75 | |||
| 70 | Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); | 76 | Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); |
| 71 | Core::g_app_core->SetReg(1, service->GetUID()); | 77 | Core::g_app_core->SetReg(1, service->GetUID()); |
| 78 | DEBUG_LOG(SVC, "ConnectToPort called port_name=%s", port_name); | ||
| 72 | return 0; | 79 | return 0; |
| 73 | } | 80 | } |
| 74 | 81 | ||
| 75 | /// Synchronize to an OS service | 82 | /// Synchronize to an OS service |
| 76 | Result SendSyncRequest(Handle session) { | 83 | Result SendSyncRequest(Handle session) { |
| 84 | DEBUG_LOG(SVC, "SendSyncRequest called session=0x%08X"); | ||
| 77 | Service::Interface* service = Service::g_manager->FetchFromUID(session); | 85 | Service::Interface* service = Service::g_manager->FetchFromUID(session); |
| 78 | service->Sync(); | 86 | service->Sync(); |
| 79 | return 0; | 87 | return 0; |
| @@ -82,142 +90,177 @@ Result SendSyncRequest(Handle session) { | |||
| 82 | /// Close a handle | 90 | /// Close a handle |
| 83 | Result CloseHandle(Handle handle) { | 91 | Result CloseHandle(Handle handle) { |
| 84 | // ImplementMe | 92 | // ImplementMe |
| 93 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) CloseHandle called handle=0x%08X", handle); | ||
| 85 | return 0; | 94 | return 0; |
| 86 | } | 95 | } |
| 87 | 96 | ||
| 88 | /// Wait for a handle to synchronize, timeout after the specified nanoseconds | 97 | /// Wait for a handle to synchronize, timeout after the specified nanoseconds |
| 89 | Result WaitSynchronization1(Handle handle, s64 nanoseconds) { | 98 | Result WaitSynchronization1(Handle handle, s64 nanoseconds) { |
| 90 | // ImplementMe | 99 | // ImplementMe |
| 100 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) WaitSynchronization1 called handle=0x%08X, nanoseconds=%d", | ||
| 101 | handle, nanoseconds); | ||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | /// Create an address arbiter (to allocate access to shared resources) | ||
| 106 | Result CreateAddressArbiter(void* arbiter) { | ||
| 107 | // ImplementMe | ||
| 108 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateAddressArbiter called"); | ||
| 109 | Core::g_app_core->SetReg(1, 0xDEADBEEF); | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit | ||
| 114 | void OutputDebugString(const char* string) { | ||
| 115 | NOTICE_LOG(SVC, "## OSDEBUG: %08X %s", Core::g_app_core->GetPC(), string); | ||
| 116 | } | ||
| 117 | |||
| 118 | /// Get resource limit | ||
| 119 | Result GetResourceLimit(void* resource_limit, Handle process) { | ||
| 120 | // With regards to proceess values: | ||
| 121 | // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for | ||
| 122 | // the current KThread. | ||
| 123 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimit called process=0x%08X", process); | ||
| 124 | Core::g_app_core->SetReg(1, 0xDEADBEEF); | ||
| 125 | return 0; | ||
| 126 | } | ||
| 127 | |||
| 128 | /// Get resource limit current values | ||
| 129 | Result GetResourceLimitCurrentValues(void* _values, Handle resource_limit, void* names, s32 name_count) { | ||
| 130 | //s64* values = (s64*)_values; | ||
| 131 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimitCurrentValues called resource_limit=%08X, names=%s, name_count=%d", | ||
| 132 | resource_limit, names, name_count); | ||
| 133 | Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now | ||
| 91 | return 0; | 134 | return 0; |
| 92 | } | 135 | } |
| 93 | 136 | ||
| 94 | const HLE::FunctionDef Syscall_Table[] = { | 137 | const HLE::FunctionDef Syscall_Table[] = { |
| 95 | {0x00, NULL, "Unknown"}, | 138 | {0x00, NULL, "Unknown"}, |
| 96 | {0x01, WrapI_UUUUU<ControlMemory>, "ControlMemory"}, | 139 | {0x01, WrapI_UUUUU<ControlMemory>, "ControlMemory"}, |
| 97 | {0x02, NULL, "QueryMemory"}, | 140 | {0x02, NULL, "QueryMemory"}, |
| 98 | {0x03, NULL, "ExitProcess"}, | 141 | {0x03, NULL, "ExitProcess"}, |
| 99 | {0x04, NULL, "GetProcessAffinityMask"}, | 142 | {0x04, NULL, "GetProcessAffinityMask"}, |
| 100 | {0x05, NULL, "SetProcessAffinityMask"}, | 143 | {0x05, NULL, "SetProcessAffinityMask"}, |
| 101 | {0x06, NULL, "GetProcessIdealProcessor"}, | 144 | {0x06, NULL, "GetProcessIdealProcessor"}, |
| 102 | {0x07, NULL, "SetProcessIdealProcessor"}, | 145 | {0x07, NULL, "SetProcessIdealProcessor"}, |
| 103 | {0x08, NULL, "CreateThread"}, | 146 | {0x08, NULL, "CreateThread"}, |
| 104 | {0x09, NULL, "ExitThread"}, | 147 | {0x09, NULL, "ExitThread"}, |
| 105 | {0x0A, NULL, "SleepThread"}, | 148 | {0x0A, NULL, "SleepThread"}, |
| 106 | {0x0B, NULL, "GetThreadPriority"}, | 149 | {0x0B, NULL, "GetThreadPriority"}, |
| 107 | {0x0C, NULL, "SetThreadPriority"}, | 150 | {0x0C, NULL, "SetThreadPriority"}, |
| 108 | {0x0D, NULL, "GetThreadAffinityMask"}, | 151 | {0x0D, NULL, "GetThreadAffinityMask"}, |
| 109 | {0x0E, NULL, "SetThreadAffinityMask"}, | 152 | {0x0E, NULL, "SetThreadAffinityMask"}, |
| 110 | {0x0F, NULL, "GetThreadIdealProcessor"}, | 153 | {0x0F, NULL, "GetThreadIdealProcessor"}, |
| 111 | {0x10, NULL, "SetThreadIdealProcessor"}, | 154 | {0x10, NULL, "SetThreadIdealProcessor"}, |
| 112 | {0x11, NULL, "GetCurrentProcessorNumber"}, | 155 | {0x11, NULL, "GetCurrentProcessorNumber"}, |
| 113 | {0x12, NULL, "Run"}, | 156 | {0x12, NULL, "Run"}, |
| 114 | {0x13, NULL, "CreateMutex"}, | 157 | {0x13, NULL, "CreateMutex"}, |
| 115 | {0x14, NULL, "ReleaseMutex"}, | 158 | {0x14, NULL, "ReleaseMutex"}, |
| 116 | {0x15, NULL, "CreateSemaphore"}, | 159 | {0x15, NULL, "CreateSemaphore"}, |
| 117 | {0x16, NULL, "ReleaseSemaphore"}, | 160 | {0x16, NULL, "ReleaseSemaphore"}, |
| 118 | {0x17, NULL, "CreateEvent"}, | 161 | {0x17, NULL, "CreateEvent"}, |
| 119 | {0x18, NULL, "SignalEvent"}, | 162 | {0x18, NULL, "SignalEvent"}, |
| 120 | {0x19, NULL, "ClearEvent"}, | 163 | {0x19, NULL, "ClearEvent"}, |
| 121 | {0x1A, NULL, "CreateTimer"}, | 164 | {0x1A, NULL, "CreateTimer"}, |
| 122 | {0x1B, NULL, "SetTimer"}, | 165 | {0x1B, NULL, "SetTimer"}, |
| 123 | {0x1C, NULL, "CancelTimer"}, | 166 | {0x1C, NULL, "CancelTimer"}, |
| 124 | {0x1D, NULL, "ClearTimer"}, | 167 | {0x1D, NULL, "ClearTimer"}, |
| 125 | {0x1E, NULL, "CreateMemoryBlock"}, | 168 | {0x1E, NULL, "CreateMemoryBlock"}, |
| 126 | {0x1F, WrapI_UUUU<MapMemoryBlock>, "MapMemoryBlock"}, | 169 | {0x1F, WrapI_UUUU<MapMemoryBlock>, "MapMemoryBlock"}, |
| 127 | {0x20, NULL, "UnmapMemoryBlock"}, | 170 | {0x20, NULL, "UnmapMemoryBlock"}, |
| 128 | {0x21, NULL, "CreateAddressArbiter"}, | 171 | {0x21, WrapI_V<CreateAddressArbiter>, "CreateAddressArbiter"}, |
| 129 | {0x22, NULL, "ArbitrateAddress"}, | 172 | {0x22, NULL, "ArbitrateAddress"}, |
| 130 | {0x23, WrapI_U<CloseHandle>, "CloseHandle"}, | 173 | {0x23, WrapI_U<CloseHandle>, "CloseHandle"}, |
| 131 | {0x24, WrapI_US64<WaitSynchronization1>, "WaitSynchronization1"}, | 174 | {0x24, WrapI_US64<WaitSynchronization1>, "WaitSynchronization1"}, |
| 132 | {0x25, NULL, "WaitSynchronizationN"}, | 175 | {0x25, NULL, "WaitSynchronizationN"}, |
| 133 | {0x26, NULL, "SignalAndWait"}, | 176 | {0x26, NULL, "SignalAndWait"}, |
| 134 | {0x27, NULL, "DuplicateHandle"}, | 177 | {0x27, NULL, "DuplicateHandle"}, |
| 135 | {0x28, NULL, "GetSystemTick"}, | 178 | {0x28, NULL, "GetSystemTick"}, |
| 136 | {0x29, NULL, "GetHandleInfo"}, | 179 | {0x29, NULL, "GetHandleInfo"}, |
| 137 | {0x2A, NULL, "GetSystemInfo"}, | 180 | {0x2A, NULL, "GetSystemInfo"}, |
| 138 | {0x2B, NULL, "GetProcessInfo"}, | 181 | {0x2B, NULL, "GetProcessInfo"}, |
| 139 | {0x2C, NULL, "GetThreadInfo"}, | 182 | {0x2C, NULL, "GetThreadInfo"}, |
| 140 | {0x2D, WrapI_VC<ConnectToPort>, "ConnectToPort"}, | 183 | {0x2D, WrapI_VC<ConnectToPort>, "ConnectToPort"}, |
| 141 | {0x2E, NULL, "SendSyncRequest1"}, | 184 | {0x2E, NULL, "SendSyncRequest1"}, |
| 142 | {0x2F, NULL, "SendSyncRequest2"}, | 185 | {0x2F, NULL, "SendSyncRequest2"}, |
| 143 | {0x30, NULL, "SendSyncRequest3"}, | 186 | {0x30, NULL, "SendSyncRequest3"}, |
| 144 | {0x31, NULL, "SendSyncRequest4"}, | 187 | {0x31, NULL, "SendSyncRequest4"}, |
| 145 | {0x32, WrapI_U<SendSyncRequest>, "SendSyncRequest"}, | 188 | {0x32, WrapI_U<SendSyncRequest>, "SendSyncRequest"}, |
| 146 | {0x33, NULL, "OpenProcess"}, | 189 | {0x33, NULL, "OpenProcess"}, |
| 147 | {0x34, NULL, "OpenThread"}, | 190 | {0x34, NULL, "OpenThread"}, |
| 148 | {0x35, NULL, "GetProcessId"}, | 191 | {0x35, NULL, "GetProcessId"}, |
| 149 | {0x36, NULL, "GetProcessIdOfThread"}, | 192 | {0x36, NULL, "GetProcessIdOfThread"}, |
| 150 | {0x37, NULL, "GetThreadId"}, | 193 | {0x37, NULL, "GetThreadId"}, |
| 151 | {0x38, NULL, "GetResourceLimit"}, | 194 | {0x38, WrapI_VU<GetResourceLimit>, "GetResourceLimit"}, |
| 152 | {0x39, NULL, "GetResourceLimitLimitValues"}, | 195 | {0x39, NULL, "GetResourceLimitLimitValues"}, |
| 153 | {0x3A, NULL, "GetResourceLimitCurrentValues"}, | 196 | {0x3A, WrapI_VUVI<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"}, |
| 154 | {0x3B, NULL, "GetThreadContext"}, | 197 | {0x3B, NULL, "GetThreadContext"}, |
| 155 | {0x3C, NULL, "Break"}, | 198 | {0x3C, NULL, "Break"}, |
| 156 | {0x3D, NULL, "OutputDebugString"}, | 199 | {0x3D, WrapV_C<OutputDebugString>, "OutputDebugString"}, |
| 157 | {0x3E, NULL, "ControlPerformanceCounter"}, | 200 | {0x3E, NULL, "ControlPerformanceCounter"}, |
| 158 | {0x3F, NULL, "Unknown"}, | 201 | {0x3F, NULL, "Unknown"}, |
| 159 | {0x40, NULL, "Unknown"}, | 202 | {0x40, NULL, "Unknown"}, |
| 160 | {0x41, NULL, "Unknown"}, | 203 | {0x41, NULL, "Unknown"}, |
| 161 | {0x42, NULL, "Unknown"}, | 204 | {0x42, NULL, "Unknown"}, |
| 162 | {0x43, NULL, "Unknown"}, | 205 | {0x43, NULL, "Unknown"}, |
| 163 | {0x44, NULL, "Unknown"}, | 206 | {0x44, NULL, "Unknown"}, |
| 164 | {0x45, NULL, "Unknown"}, | 207 | {0x45, NULL, "Unknown"}, |
| 165 | {0x46, NULL, "Unknown"}, | 208 | {0x46, NULL, "Unknown"}, |
| 166 | {0x47, NULL, "CreatePort"}, | 209 | {0x47, NULL, "CreatePort"}, |
| 167 | {0x48, NULL, "CreateSessionToPort"}, | 210 | {0x48, NULL, "CreateSessionToPort"}, |
| 168 | {0x49, NULL, "CreateSession"}, | 211 | {0x49, NULL, "CreateSession"}, |
| 169 | {0x4A, NULL, "AcceptSession"}, | 212 | {0x4A, NULL, "AcceptSession"}, |
| 170 | {0x4B, NULL, "ReplyAndReceive1"}, | 213 | {0x4B, NULL, "ReplyAndReceive1"}, |
| 171 | {0x4C, NULL, "ReplyAndReceive2"}, | 214 | {0x4C, NULL, "ReplyAndReceive2"}, |
| 172 | {0x4D, NULL, "ReplyAndReceive3"}, | 215 | {0x4D, NULL, "ReplyAndReceive3"}, |
| 173 | {0x4E, NULL, "ReplyAndReceive4"}, | 216 | {0x4E, NULL, "ReplyAndReceive4"}, |
| 174 | {0x4F, NULL, "ReplyAndReceive"}, | 217 | {0x4F, NULL, "ReplyAndReceive"}, |
| 175 | {0x50, NULL, "BindInterrupt"}, | 218 | {0x50, NULL, "BindInterrupt"}, |
| 176 | {0x51, NULL, "UnbindInterrupt"}, | 219 | {0x51, NULL, "UnbindInterrupt"}, |
| 177 | {0x52, NULL, "InvalidateProcessDataCache"}, | 220 | {0x52, NULL, "InvalidateProcessDataCache"}, |
| 178 | {0x53, NULL, "StoreProcessDataCache"}, | 221 | {0x53, NULL, "StoreProcessDataCache"}, |
| 179 | {0x54, NULL, "FlushProcessDataCache"}, | 222 | {0x54, NULL, "FlushProcessDataCache"}, |
| 180 | {0x55, NULL, "StartInterProcessDma"}, | 223 | {0x55, NULL, "StartInterProcessDma"}, |
| 181 | {0x56, NULL, "StopDma"}, | 224 | {0x56, NULL, "StopDma"}, |
| 182 | {0x57, NULL, "GetDmaState"}, | 225 | {0x57, NULL, "GetDmaState"}, |
| 183 | {0x58, NULL, "RestartDma"}, | 226 | {0x58, NULL, "RestartDma"}, |
| 184 | {0x59, NULL, "Unknown"}, | 227 | {0x59, NULL, "Unknown"}, |
| 185 | {0x5A, NULL, "Unknown"}, | 228 | {0x5A, NULL, "Unknown"}, |
| 186 | {0x5B, NULL, "Unknown"}, | 229 | {0x5B, NULL, "Unknown"}, |
| 187 | {0x5C, NULL, "Unknown"}, | 230 | {0x5C, NULL, "Unknown"}, |
| 188 | {0x5D, NULL, "Unknown"}, | 231 | {0x5D, NULL, "Unknown"}, |
| 189 | {0x5E, NULL, "Unknown"}, | 232 | {0x5E, NULL, "Unknown"}, |
| 190 | {0x5F, NULL, "Unknown"}, | 233 | {0x5F, NULL, "Unknown"}, |
| 191 | {0x60, NULL, "DebugActiveProcess"}, | 234 | {0x60, NULL, "DebugActiveProcess"}, |
| 192 | {0x61, NULL, "BreakDebugProcess"}, | 235 | {0x61, NULL, "BreakDebugProcess"}, |
| 193 | {0x62, NULL, "TerminateDebugProcess"}, | 236 | {0x62, NULL, "TerminateDebugProcess"}, |
| 194 | {0x63, NULL, "GetProcessDebugEvent"}, | 237 | {0x63, NULL, "GetProcessDebugEvent"}, |
| 195 | {0x64, NULL, "ContinueDebugEvent"}, | 238 | {0x64, NULL, "ContinueDebugEvent"}, |
| 196 | {0x65, NULL, "GetProcessList"}, | 239 | {0x65, NULL, "GetProcessList"}, |
| 197 | {0x66, NULL, "GetThreadList"}, | 240 | {0x66, NULL, "GetThreadList"}, |
| 198 | {0x67, NULL, "GetDebugThreadContext"}, | 241 | {0x67, NULL, "GetDebugThreadContext"}, |
| 199 | {0x68, NULL, "SetDebugThreadContext"}, | 242 | {0x68, NULL, "SetDebugThreadContext"}, |
| 200 | {0x69, NULL, "QueryDebugProcessMemory"}, | 243 | {0x69, NULL, "QueryDebugProcessMemory"}, |
| 201 | {0x6A, NULL, "ReadProcessMemory"}, | 244 | {0x6A, NULL, "ReadProcessMemory"}, |
| 202 | {0x6B, NULL, "WriteProcessMemory"}, | 245 | {0x6B, NULL, "WriteProcessMemory"}, |
| 203 | {0x6C, NULL, "SetHardwareBreakPoint"}, | 246 | {0x6C, NULL, "SetHardwareBreakPoint"}, |
| 204 | {0x6D, NULL, "GetDebugThreadParam"}, | 247 | {0x6D, NULL, "GetDebugThreadParam"}, |
| 205 | {0x6E, NULL, "Unknown"}, | 248 | {0x6E, NULL, "Unknown"}, |
| 206 | {0x6F, NULL, "Unknown"}, | 249 | {0x6F, NULL, "Unknown"}, |
| 207 | {0x70, NULL, "ControlProcessMemory"}, | 250 | {0x70, NULL, "ControlProcessMemory"}, |
| 208 | {0x71, NULL, "MapProcessMemory"}, | 251 | {0x71, NULL, "MapProcessMemory"}, |
| 209 | {0x72, NULL, "UnmapProcessMemory"}, | 252 | {0x72, NULL, "UnmapProcessMemory"}, |
| 210 | {0x73, NULL, "Unknown"}, | 253 | {0x73, NULL, "Unknown"}, |
| 211 | {0x74, NULL, "Unknown"}, | 254 | {0x74, NULL, "Unknown"}, |
| 212 | {0x75, NULL, "Unknown"}, | 255 | {0x75, NULL, "Unknown"}, |
| 213 | {0x76, NULL, "TerminateProcess"}, | 256 | {0x76, NULL, "TerminateProcess"}, |
| 214 | {0x77, NULL, "Unknown"}, | 257 | {0x77, NULL, "Unknown"}, |
| 215 | {0x78, NULL, "CreateResourceLimit"}, | 258 | {0x78, NULL, "CreateResourceLimit"}, |
| 216 | {0x79, NULL, "Unknown"}, | 259 | {0x79, NULL, "Unknown"}, |
| 217 | {0x7A, NULL, "Unknown"}, | 260 | {0x7A, NULL, "Unknown"}, |
| 218 | {0x7B, NULL, "Unknown"}, | 261 | {0x7B, NULL, "Unknown"}, |
| 219 | {0x7C, NULL, "KernelSetState"}, | 262 | {0x7C, NULL, "KernelSetState"}, |
| 220 | {0x7D, NULL, "QueryProcessMemory"}, | 263 | {0x7D, NULL, "QueryProcessMemory"}, |
| 221 | }; | 264 | }; |
| 222 | 265 | ||
| 223 | void Register() { | 266 | void Register() { |
diff --git a/src/core/loader.cpp b/src/core/loader.cpp index 7c1dfef61..8756588ae 100644 --- a/src/core/loader.cpp +++ b/src/core/loader.cpp | |||
| @@ -89,8 +89,8 @@ bool Load_DAT(std::string &filename) { | |||
| 89 | * but for the sake of making it easier... we'll temporarily/hackishly | 89 | * but for the sake of making it easier... we'll temporarily/hackishly |
| 90 | * allow it. No sense in making a proper reader for this. | 90 | * allow it. No sense in making a proper reader for this. |
| 91 | */ | 91 | */ |
| 92 | u32 entrypoint = 0x080c3ee0; // write to same entrypoint as elf | 92 | u32 entrypoint = 0x00100000; // write to same entrypoint as elf |
| 93 | u32 payload_offset = 0x6F4; | 93 | u32 payload_offset = 0xA150; |
| 94 | 94 | ||
| 95 | const u8 *src = &buffer[payload_offset]; | 95 | const u8 *src = &buffer[payload_offset]; |
| 96 | u8 *dst = Memory::GetPointer(entrypoint); | 96 | u8 *dst = Memory::GetPointer(entrypoint); |
| @@ -114,6 +114,47 @@ bool Load_DAT(std::string &filename) { | |||
| 114 | return true; | 114 | return true; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | |||
| 118 | /// Loads a CTR BIN file extracted from an ExeFS | ||
| 119 | bool Load_BIN(std::string &filename) { | ||
| 120 | std::string full_path = filename; | ||
| 121 | std::string path, file, extension; | ||
| 122 | SplitPath(ReplaceAll(full_path, "\\", "/"), &path, &file, &extension); | ||
| 123 | #if EMU_PLATFORM == PLATFORM_WINDOWS | ||
| 124 | path = ReplaceAll(path, "/", "\\"); | ||
| 125 | #endif | ||
| 126 | File::IOFile f(filename, "rb"); | ||
| 127 | |||
| 128 | if (f.IsOpen()) { | ||
| 129 | u64 size = f.GetSize(); | ||
| 130 | u8* buffer = new u8[size]; | ||
| 131 | |||
| 132 | f.ReadBytes(buffer, size); | ||
| 133 | |||
| 134 | u32 entrypoint = 0x00100000; // Hardcoded, read from exheader | ||
| 135 | |||
| 136 | const u8 *src = buffer; | ||
| 137 | u8 *dst = Memory::GetPointer(entrypoint); | ||
| 138 | u32 srcSize = size; | ||
| 139 | u32 *s = (u32*)src; | ||
| 140 | u32 *d = (u32*)dst; | ||
| 141 | for (int j = 0; j < (int)(srcSize + 3) / 4; j++) | ||
| 142 | { | ||
| 143 | *d++ = (*s++); | ||
| 144 | } | ||
| 145 | |||
| 146 | Core::g_app_core->SetPC(entrypoint); | ||
| 147 | |||
| 148 | delete[] buffer; | ||
| 149 | } | ||
| 150 | else { | ||
| 151 | return false; | ||
| 152 | } | ||
| 153 | f.Close(); | ||
| 154 | |||
| 155 | return true; | ||
| 156 | } | ||
| 157 | |||
| 117 | namespace Loader { | 158 | namespace Loader { |
| 118 | 159 | ||
| 119 | bool IsBootableDirectory() { | 160 | bool IsBootableDirectory() { |
| @@ -145,6 +186,9 @@ FileType IdentifyFile(std::string &filename) { | |||
| 145 | else if (!strcasecmp(extension.c_str(), ".elf")) { | 186 | else if (!strcasecmp(extension.c_str(), ".elf")) { |
| 146 | return FILETYPE_CTR_ELF; // TODO(bunnei): Do some filetype checking :p | 187 | return FILETYPE_CTR_ELF; // TODO(bunnei): Do some filetype checking :p |
| 147 | } | 188 | } |
| 189 | else if (!strcasecmp(extension.c_str(), ".bin")) { | ||
| 190 | return FILETYPE_CTR_BIN; | ||
| 191 | } | ||
| 148 | else if (!strcasecmp(extension.c_str(), ".dat")) { | 192 | else if (!strcasecmp(extension.c_str(), ".dat")) { |
| 149 | return FILETYPE_LAUNCHER_DAT; | 193 | return FILETYPE_LAUNCHER_DAT; |
| 150 | } | 194 | } |
| @@ -178,6 +222,9 @@ bool LoadFile(std::string &filename, std::string *error_string) { | |||
| 178 | case FILETYPE_CTR_ELF: | 222 | case FILETYPE_CTR_ELF: |
| 179 | return Load_ELF(filename); | 223 | return Load_ELF(filename); |
| 180 | 224 | ||
| 225 | case FILETYPE_CTR_BIN: | ||
| 226 | return Load_BIN(filename); | ||
| 227 | |||
| 181 | case FILETYPE_LAUNCHER_DAT: | 228 | case FILETYPE_LAUNCHER_DAT: |
| 182 | return Load_DAT(filename); | 229 | return Load_DAT(filename); |
| 183 | 230 | ||
| @@ -215,7 +262,7 @@ bool LoadFile(std::string &filename, std::string *error_string) { | |||
| 215 | case FILETYPE_UNKNOWN: | 262 | case FILETYPE_UNKNOWN: |
| 216 | default: | 263 | default: |
| 217 | ERROR_LOG(LOADER, "Failed to identify file"); | 264 | ERROR_LOG(LOADER, "Failed to identify file"); |
| 218 | *error_string = "Failed to identify file"; | 265 | *error_string = " Failed to identify file"; |
| 219 | break; | 266 | break; |
| 220 | } | 267 | } |
| 221 | return false; | 268 | return false; |
diff --git a/src/core/loader.h b/src/core/loader.h index df30f16c7..9d4aaa874 100644 --- a/src/core/loader.h +++ b/src/core/loader.h | |||
| @@ -17,19 +17,21 @@ enum FileType { | |||
| 17 | FILETYPE_CTR_CIA, | 17 | FILETYPE_CTR_CIA, |
| 18 | FILETYPE_CTR_CXI, | 18 | FILETYPE_CTR_CXI, |
| 19 | FILETYPE_CTR_ELF, | 19 | FILETYPE_CTR_ELF, |
| 20 | FILETYPE_LAUNCHER_DAT, | 20 | FILETYPE_CTR_BIN, |
| 21 | |||
| 22 | FILETYPE_DIRECTORY_CXI, | ||
| 23 | |||
| 24 | FILETYPE_UNKNOWN_BIN, | ||
| 25 | FILETYPE_UNKNOWN_ELF, | ||
| 26 | 21 | ||
| 27 | FILETYPE_ARCHIVE_RAR, | 22 | FILETYPE_LAUNCHER_DAT, |
| 28 | FILETYPE_ARCHIVE_ZIP, | ||
| 29 | |||
| 30 | FILETYPE_NORMAL_DIRECTORY, | ||
| 31 | 23 | ||
| 32 | FILETYPE_UNKNOWN | 24 | FILETYPE_DIRECTORY_CXI, |
| 25 | |||
| 26 | FILETYPE_UNKNOWN_BIN, | ||
| 27 | FILETYPE_UNKNOWN_ELF, | ||
| 28 | |||
| 29 | FILETYPE_ARCHIVE_RAR, | ||
| 30 | FILETYPE_ARCHIVE_ZIP, | ||
| 31 | |||
| 32 | FILETYPE_NORMAL_DIRECTORY, | ||
| 33 | |||
| 34 | FILETYPE_UNKNOWN | ||
| 33 | }; | 35 | }; |
| 34 | 36 | ||
| 35 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 37 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/mem_map.cpp b/src/core/mem_map.cpp index af99cbe32..59560b87d 100644 --- a/src/core/mem_map.cpp +++ b/src/core/mem_map.cpp | |||
| @@ -21,6 +21,7 @@ u8* g_heap = NULL; ///< Application heap (main memo | |||
| 21 | u8* g_heap_gsp = NULL; ///< GSP heap (main memory) | 21 | u8* g_heap_gsp = NULL; ///< GSP heap (main memory) |
| 22 | u8* g_vram = NULL; ///< Video memory (VRAM) pointer | 22 | u8* g_vram = NULL; ///< Video memory (VRAM) pointer |
| 23 | u8* g_shared_mem = NULL; ///< Shared memory | 23 | u8* g_shared_mem = NULL; ///< Shared memory |
| 24 | u8* g_kernel_mem; ///< Kernel memory | ||
| 24 | 25 | ||
| 25 | u8* g_physical_bootrom = NULL; ///< Bootrom physical memory | 26 | u8* g_physical_bootrom = NULL; ///< Bootrom physical memory |
| 26 | u8* g_uncached_bootrom = NULL; | 27 | u8* g_uncached_bootrom = NULL; |
| @@ -30,6 +31,7 @@ u8* g_physical_fcram = NULL; ///< Main physical memory (FCRAM | |||
| 30 | u8* g_physical_heap_gsp = NULL; ///< GSP heap physical memory | 31 | u8* g_physical_heap_gsp = NULL; ///< GSP heap physical memory |
| 31 | u8* g_physical_vram = NULL; ///< Video physical memory (VRAM) | 32 | u8* g_physical_vram = NULL; ///< Video physical memory (VRAM) |
| 32 | u8* g_physical_shared_mem = NULL; ///< Physical shared memory | 33 | u8* g_physical_shared_mem = NULL; ///< Physical shared memory |
| 34 | u8* g_physical_kernel_mem; ///< Kernel memory | ||
| 33 | 35 | ||
| 34 | // We don't declare the IO region in here since its handled by other means. | 36 | // We don't declare the IO region in here since its handled by other means. |
| 35 | static MemoryView g_views[] = { | 37 | static MemoryView g_views[] = { |
| @@ -37,6 +39,7 @@ static MemoryView g_views[] = { | |||
| 37 | {&g_vram, &g_physical_vram, VRAM_VADDR, VRAM_SIZE, 0}, | 39 | {&g_vram, &g_physical_vram, VRAM_VADDR, VRAM_SIZE, 0}, |
| 38 | {&g_heap, &g_physical_fcram, HEAP_VADDR, HEAP_SIZE, MV_IS_PRIMARY_RAM}, | 40 | {&g_heap, &g_physical_fcram, HEAP_VADDR, HEAP_SIZE, MV_IS_PRIMARY_RAM}, |
| 39 | {&g_shared_mem, &g_physical_shared_mem, SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, 0}, | 41 | {&g_shared_mem, &g_physical_shared_mem, SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, 0}, |
| 42 | {&g_kernel_mem, &g_physical_kernel_mem, KERNEL_MEMORY_VADDR, KERNEL_MEMORY_SIZE, 0}, | ||
| 40 | {&g_heap_gsp, &g_physical_heap_gsp, HEAP_GSP_VADDR, HEAP_GSP_SIZE, 0}, | 43 | {&g_heap_gsp, &g_physical_heap_gsp, HEAP_GSP_VADDR, HEAP_GSP_SIZE, 0}, |
| 41 | }; | 44 | }; |
| 42 | 45 | ||
diff --git a/src/core/mem_map.h b/src/core/mem_map.h index 62a8b82a8..af2212a5f 100644 --- a/src/core/mem_map.h +++ b/src/core/mem_map.h | |||
| @@ -32,6 +32,16 @@ enum { | |||
| 32 | SHARED_MEMORY_VADDR_END = (SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE), | 32 | SHARED_MEMORY_VADDR_END = (SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE), |
| 33 | SHARED_MEMORY_MASK = (SHARED_MEMORY_SIZE - 1), | 33 | SHARED_MEMORY_MASK = (SHARED_MEMORY_SIZE - 1), |
| 34 | 34 | ||
| 35 | CONFIG_MEMORY_SIZE = 0x00001000, ///< Configuration memory size | ||
| 36 | CONFIG_MEMORY_VADDR = 0x1FF80000, ///< Configuration memory virtual address | ||
| 37 | CONFIG_MEMORY_VADDR_END = (CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE), | ||
| 38 | CONFIG_MEMORY_MASK = (CONFIG_MEMORY_SIZE - 1), | ||
| 39 | |||
| 40 | KERNEL_MEMORY_SIZE = 0x00001000, ///< Kernel memory size | ||
| 41 | KERNEL_MEMORY_VADDR = 0xFFFF0000, ///< Kernel memory where the kthread objects etc are | ||
| 42 | KERNEL_MEMORY_VADDR_END = (KERNEL_MEMORY_VADDR + KERNEL_MEMORY_SIZE), | ||
| 43 | KERNEL_MEMORY_MASK = (KERNEL_MEMORY_SIZE - 1), | ||
| 44 | |||
| 35 | EXEFS_CODE_SIZE = 0x03F00000, | 45 | EXEFS_CODE_SIZE = 0x03F00000, |
| 36 | EXEFS_CODE_VADDR = 0x00100000, ///< ExeFS:/.code is loaded here | 46 | EXEFS_CODE_VADDR = 0x00100000, ///< ExeFS:/.code is loaded here |
| 37 | EXEFS_CODE_VADDR_END = (EXEFS_CODE_VADDR + EXEFS_CODE_SIZE), | 47 | EXEFS_CODE_VADDR_END = (EXEFS_CODE_VADDR + EXEFS_CODE_SIZE), |
| @@ -105,6 +115,7 @@ extern u8* g_heap_gsp; ///< GSP heap (main memory) | |||
| 105 | extern u8* g_heap; ///< Application heap (main memory) | 115 | extern u8* g_heap; ///< Application heap (main memory) |
| 106 | extern u8* g_vram; ///< Video memory (VRAM) | 116 | extern u8* g_vram; ///< Video memory (VRAM) |
| 107 | extern u8* g_shared_mem; ///< Shared memory | 117 | extern u8* g_shared_mem; ///< Shared memory |
| 118 | extern u8* g_kernel_mem; ///< Kernel memory | ||
| 108 | extern u8* g_exefs_code; ///< ExeFS:/.code is loaded here | 119 | extern u8* g_exefs_code; ///< ExeFS:/.code is loaded here |
| 109 | 120 | ||
| 110 | void Init(); | 121 | void Init(); |
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp index 2284b535c..8ab647714 100644 --- a/src/core/mem_map_funcs.cpp +++ b/src/core/mem_map_funcs.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "core/mem_map.h" | 9 | #include "core/mem_map.h" |
| 10 | #include "core/hw/hw.h" | 10 | #include "core/hw/hw.h" |
| 11 | #include "hle/hle.h" | 11 | #include "hle/hle.h" |
| 12 | #include "hle/config_mem.h" | ||
| 12 | 13 | ||
| 13 | namespace Memory { | 14 | namespace Memory { |
| 14 | 15 | ||
| @@ -46,12 +47,10 @@ inline void _Read(T &var, const u32 addr) { | |||
| 46 | // Could just do a base-relative read, too.... TODO | 47 | // Could just do a base-relative read, too.... TODO |
| 47 | 48 | ||
| 48 | const u32 vaddr = _VirtualAddress(addr); | 49 | const u32 vaddr = _VirtualAddress(addr); |
| 49 | 50 | ||
| 50 | // Memory allocated for HLE use that can be addressed from the emulated application | 51 | // Kernel memory command buffer |
| 51 | // The primary use of this is sharing a commandbuffer between the HLE OS (syscore) and the LLE | 52 | if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) { |
| 52 | // core running the user application (appcore) | 53 | var = *((const T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK]); |
| 53 | if (vaddr >= HLE::CMD_BUFFER_ADDR && vaddr < HLE::CMD_BUFFER_ADDR_END) { | ||
| 54 | HLE::Read<T>(var, vaddr); | ||
| 55 | 54 | ||
| 56 | // Hardware I/O register reads | 55 | // Hardware I/O register reads |
| 57 | // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space | 56 | // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space |
| @@ -74,6 +73,10 @@ inline void _Read(T &var, const u32 addr) { | |||
| 74 | } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) { | 73 | } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) { |
| 75 | var = *((const T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK]); | 74 | var = *((const T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK]); |
| 76 | 75 | ||
| 76 | // Config memory | ||
| 77 | } else if ((vaddr >= CONFIG_MEMORY_VADDR) && (vaddr < CONFIG_MEMORY_VADDR_END)) { | ||
| 78 | ConfigMem::Read<T>(var, vaddr); | ||
| 79 | |||
| 77 | // VRAM | 80 | // VRAM |
| 78 | } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) { | 81 | } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) { |
| 79 | var = *((const T*)&g_vram[vaddr & VRAM_MASK]); | 82 | var = *((const T*)&g_vram[vaddr & VRAM_MASK]); |
| @@ -87,11 +90,9 @@ template <typename T> | |||
| 87 | inline void _Write(u32 addr, const T data) { | 90 | inline void _Write(u32 addr, const T data) { |
| 88 | u32 vaddr = _VirtualAddress(addr); | 91 | u32 vaddr = _VirtualAddress(addr); |
| 89 | 92 | ||
| 90 | // Memory allocated for HLE use that can be addressed from the emulated application | 93 | // Kernel memory command buffer |
| 91 | // The primary use of this is sharing a commandbuffer between the HLE OS (syscore) and the LLE | 94 | if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) { |
| 92 | // core running the user application (appcore) | 95 | *(T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK] = data; |
| 93 | if (vaddr >= HLE::CMD_BUFFER_ADDR && vaddr < HLE::CMD_BUFFER_ADDR_END) { | ||
| 94 | HLE::Write<T>(vaddr, data); | ||
| 95 | 96 | ||
| 96 | // Hardware I/O register writes | 97 | // Hardware I/O register writes |
| 97 | // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space | 98 | // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space |
| @@ -118,12 +119,12 @@ inline void _Write(u32 addr, const T data) { | |||
| 118 | } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) { | 119 | } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) { |
| 119 | *(T*)&g_vram[vaddr & VRAM_MASK] = data; | 120 | *(T*)&g_vram[vaddr & VRAM_MASK] = data; |
| 120 | 121 | ||
| 121 | } else if ((vaddr & 0xFFF00000) == 0x1FF00000) { | 122 | //} else if ((vaddr & 0xFFF00000) == 0x1FF00000) { |
| 122 | _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory"); | 123 | // _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory"); |
| 123 | } else if ((vaddr & 0xFFFF0000) == 0x1FF80000) { | 124 | //} else if ((vaddr & 0xFFFF0000) == 0x1FF80000) { |
| 124 | _assert_msg_(MEMMAP, false, "umimplemented write to Configuration Memory"); | 125 | // _assert_msg_(MEMMAP, false, "umimplemented write to Configuration Memory"); |
| 125 | } else if ((vaddr & 0xFFFFF000) == 0x1FF81000) { | 126 | //} else if ((vaddr & 0xFFFFF000) == 0x1FF81000) { |
| 126 | _assert_msg_(MEMMAP, false, "umimplemented write to shared page"); | 127 | // _assert_msg_(MEMMAP, false, "umimplemented write to shared page"); |
| 127 | 128 | ||
| 128 | // Error out... | 129 | // Error out... |
| 129 | } else { | 130 | } else { |
| @@ -135,8 +136,12 @@ inline void _Write(u32 addr, const T data) { | |||
| 135 | u8 *GetPointer(const u32 addr) { | 136 | u8 *GetPointer(const u32 addr) { |
| 136 | const u32 vaddr = _VirtualAddress(addr); | 137 | const u32 vaddr = _VirtualAddress(addr); |
| 137 | 138 | ||
| 139 | // Kernel memory command buffer | ||
| 140 | if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) { | ||
| 141 | return g_kernel_mem + (vaddr & KERNEL_MEMORY_MASK); | ||
| 142 | |||
| 138 | // ExeFS:/.code is loaded here | 143 | // ExeFS:/.code is loaded here |
| 139 | if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) { | 144 | } else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) { |
| 140 | return g_exefs_code + (vaddr & EXEFS_CODE_MASK); | 145 | return g_exefs_code + (vaddr & EXEFS_CODE_MASK); |
| 141 | 146 | ||
| 142 | // FCRAM - GSP heap | 147 | // FCRAM - GSP heap |