summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/citra_qt/main.cpp10
-rw-r--r--src/citra_qt/main.hxx9
-rw-r--r--src/citra_qt/main.ui18
-rw-r--r--src/citra_qt/ui_main.h5
-rw-r--r--src/common/bit_field.h172
-rw-r--r--src/common/common.vcxproj1
-rw-r--r--src/common/common.vcxproj.filters1
-rw-r--r--src/common/log.h4
-rw-r--r--src/common/log_manager.cpp6
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/arm/disassembler/load_symbol_map.cpp33
-rw-r--r--src/core/arm/disassembler/load_symbol_map.h13
-rw-r--r--src/core/arm/interpreter/armemu.cpp39
-rw-r--r--src/core/arm/interpreter/armsupp.cpp61
-rw-r--r--src/core/arm/mmu/arm1176jzf_s_mmu.cpp6
-rw-r--r--src/core/core.vcxproj8
-rw-r--r--src/core/core.vcxproj.filters16
-rw-r--r--src/core/hle/config_mem.cpp70
-rw-r--r--src/core/hle/config_mem.h21
-rw-r--r--src/core/hle/coprocessor.cpp50
-rw-r--r--src/core/hle/coprocessor.h (renamed from src/core/hle/mrc.h)11
-rw-r--r--src/core/hle/function_wrappers.h32
-rw-r--r--src/core/hle/hle.cpp47
-rw-r--r--src/core/hle/hle.h21
-rw-r--r--src/core/hle/mrc.cpp64
-rw-r--r--src/core/hle/service/apt.cpp2
-rw-r--r--src/core/hle/service/gsp.cpp71
-rw-r--r--src/core/hle/service/service.h12
-rw-r--r--src/core/hle/service/srv.cpp2
-rw-r--r--src/core/hle/syscall.cpp301
-rw-r--r--src/core/loader.cpp53
-rw-r--r--src/core/loader.h24
-rw-r--r--src/core/mem_map.cpp3
-rw-r--r--src/core/mem_map.h11
-rw-r--r--src/core/mem_map_funcs.cpp41
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
141void GMainWindow::OnMenuLoadFile() 143void 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
150void 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
148void GMainWindow::OnStartGame() 156void 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
35private slots: 35private 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>&amp;File</string> 40 <string>&amp;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&amp;xit</string> 88 <string>E&amp;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{
28public: 28public:
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)
113template<std::size_t position, std::size_t bits, typename T>
114struct BitField
115{
116private:
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
122public:
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
146private:
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 */
18void 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 */
13void 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
26unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, 26unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
@@ -661,39 +661,40 @@ ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
661void 661void
662ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) 662ARMul_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
12namespace ConfigMem {
13
14enum {
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
32template <typename T>
33inline 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
64template void Read<u64>(u64 &var, const u32 addr);
65template void Read<u32>(u32 &var, const u32 addr);
66template void Read<u16>(u16 &var, const u32 addr);
67template 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
16namespace ConfigMem {
17
18template <typename T>
19inline 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
10namespace HLE {
11
12/// Data synchronization barrier
13u32 DataSynchronizationBarrier() {
14 return 0;
15}
16
17/// Returns the coprocessor (in this case, syscore) command buffer pointer
18Addr 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
24s32 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
32s32 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
9namespace HLE { 9namespace HLE {
10 10
11/// MRC operations (ARM register from coprocessor), decoded as instr[20:27] 11/// Coprocessor operations
12enum ARM11_MRC_OPERATION { 12enum 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
18u32 CallMRC(ARM11_MRC_OPERATION operation); 18s32 CallMCR(u32 instruction, u32 value);
19
20/// Call an MRC (move to ARM register from coprocessor) instruction in HLE
21s32 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
161template<int func()> void WrapI_V() { 161template<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
641template<void func(const char*)> void WrapV_C() {
642 func(Memory::GetCharPointer(PARAM(0)));
643}
644
641template<void func(const char *, int)> void WrapV_CI() { 645template<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
718template<int func(int, void *, void *, void *, void *, u32, int)> void WrapI_IVVVVUI(){ 722template<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
723template<int func(int, const char *, u32, void *, int, int, int)> void WrapI_ICUVIII(){ 727template<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
728template<int func(void *, u32, u32, u32, u32, u32)> void WrapI_VUUUUU(){ 732template<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
737template<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
742template<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
733template<int func(u32, s64)> void WrapI_US64() { 747template<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
16static std::vector<ModuleDef> g_module_db; 16static std::vector<ModuleDef> g_module_db;
17 17
18u8* g_command_buffer = NULL; ///< Command buffer used for sharing between appcore and syscore
19
20// Read from memory used by CTROS HLE functions
21template <typename T>
22inline 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
31template <typename T>
32inline 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
40u8 *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
51template void Read<u64>(u64 &var, const u32 addr);
52template void Read<u32>(u32 &var, const u32 addr);
53template void Read<u16>(u16 &var, const u32 addr);
54template void Read<u8>(u8 &var, const u32 addr);
55
56template void Write<u64>(u32 addr, const u64 data);
57template void Write<u32>(u32 addr, const u32 data);
58template void Write<u16>(u32 addr, const u16 data);
59template void Write<u8>(u32 addr, const u8 data);
60
61const FunctionDef* GetSyscallInfo(u32 opcode) { 18const 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
92void Init() { 49void 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() {
102void Shutdown() { 57void 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
18namespace HLE { 18namespace HLE {
19 19
20enum {
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
27typedef u32 Addr; 20typedef u32 Addr;
28typedef void (*Func)(); 21typedef 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
43template <typename T>
44inline void Read(T &var, const u32 addr);
45
46// Write to memory used by CTROS HLE functions
47template <typename T>
48inline void Write(u32 addr, const T data);
49
50u8* GetPointer(const u32 Address);
51
52inline const char* GetCharPointer(const u32 address) {
53 return (const char *)GetPointer(address);
54}
55
56void RegisterModule(std::string name, int num_functions, const FunctionDef *func_table); 35void RegisterModule(std::string name, int num_functions, const FunctionDef *func_table);
57 36
58void CallSyscall(u32 opcode); 37void 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
10namespace HLE {
11
12enum {
13 CMD_GX_REQUEST_DMA = 0x00000000,
14};
15
16/// Data synchronization barrier
17u32 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
40Addr 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
48u32 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
20void GetLockHandle(Service::Interface* self) { 20void 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
18union 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
35static 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
40static 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
45void 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
17namespace GSP_GPU { 53namespace GSP_GPU {
18 54
55u32 g_thread_id = 0;
56
57enum {
58 CMD_GX_REQUEST_DMA = 0x00000000,
59};
60
19enum { 61enum {
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
58void RegisterInterruptRelayQueue(Service::Interface* self) { 100void 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.
110void 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
67const Interface::FunctionInfo FunctionTable[] = { 128const 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
22static const int kMaxPortSize = 0x08; ///< Maximum size of a port name (8 characters) 23static const int kMaxPortSize = 0x08; ///< Maximum size of a port name (8 characters)
23static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of header 24static 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 */
31inline static u32* GetCommandBuffer(const int offset=0) {
32 return (u32*)Memory::GetPointer(Memory::KERNEL_MEMORY_VADDR + kCommandHeaderOffset + offset);
33}
34
25class Manager; 35class 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
19void GetServiceHandle(Service::Interface* self) { 19void 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 {
29Result ControlMemory(u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { 29Result 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
54Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission) { 58Result 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
69Result ConnectToPort(void* out, const char* port_name) { 74Result 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
76Result SendSyncRequest(Handle session) { 83Result 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
83Result CloseHandle(Handle handle) { 91Result 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
89Result WaitSynchronization1(Handle handle, s64 nanoseconds) { 98Result 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)
106Result 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
114void OutputDebugString(const char* string) {
115 NOTICE_LOG(SVC, "## OSDEBUG: %08X %s", Core::g_app_core->GetPC(), string);
116}
117
118/// Get resource limit
119Result 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
129Result 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
94const HLE::FunctionDef Syscall_Table[] = { 137const 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
223void Register() { 266void 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
119bool 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
117namespace Loader { 158namespace Loader {
118 159
119bool IsBootableDirectory() { 160bool 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
21u8* g_heap_gsp = NULL; ///< GSP heap (main memory) 21u8* g_heap_gsp = NULL; ///< GSP heap (main memory)
22u8* g_vram = NULL; ///< Video memory (VRAM) pointer 22u8* g_vram = NULL; ///< Video memory (VRAM) pointer
23u8* g_shared_mem = NULL; ///< Shared memory 23u8* g_shared_mem = NULL; ///< Shared memory
24u8* g_kernel_mem; ///< Kernel memory
24 25
25u8* g_physical_bootrom = NULL; ///< Bootrom physical memory 26u8* g_physical_bootrom = NULL; ///< Bootrom physical memory
26u8* g_uncached_bootrom = NULL; 27u8* g_uncached_bootrom = NULL;
@@ -30,6 +31,7 @@ u8* g_physical_fcram = NULL; ///< Main physical memory (FCRAM
30u8* g_physical_heap_gsp = NULL; ///< GSP heap physical memory 31u8* g_physical_heap_gsp = NULL; ///< GSP heap physical memory
31u8* g_physical_vram = NULL; ///< Video physical memory (VRAM) 32u8* g_physical_vram = NULL; ///< Video physical memory (VRAM)
32u8* g_physical_shared_mem = NULL; ///< Physical shared memory 33u8* g_physical_shared_mem = NULL; ///< Physical shared memory
34u8* 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.
35static MemoryView g_views[] = { 37static 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)
105extern u8* g_heap; ///< Application heap (main memory) 115extern u8* g_heap; ///< Application heap (main memory)
106extern u8* g_vram; ///< Video memory (VRAM) 116extern u8* g_vram; ///< Video memory (VRAM)
107extern u8* g_shared_mem; ///< Shared memory 117extern u8* g_shared_mem; ///< Shared memory
118extern u8* g_kernel_mem; ///< Kernel memory
108extern u8* g_exefs_code; ///< ExeFS:/.code is loaded here 119extern u8* g_exefs_code; ///< ExeFS:/.code is loaded here
109 120
110void Init(); 121void 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
13namespace Memory { 14namespace 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>
87inline void _Write(u32 addr, const T data) { 90inline 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) {
135u8 *GetPointer(const u32 addr) { 136u8 *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