diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml
new file mode 100644
index 00000000..e2b942ab
--- /dev/null
+++ b/.github/workflows/build-macos.yml
@@ -0,0 +1,39 @@
+name: CMake Build (macOS x86-64)
+
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+ branches:
+ - master
+
+env:
+ BUILD_TYPE: Release
+
+jobs:
+ build:
+
+ runs-on: macos-latest
+
+ steps:
+ - uses: actions/checkout@v1
+ - name: Install dependencies
+ working-directory: ${{runner.workspace}}
+ run: |
+ brew install cmake sdl2 qt5 libslirp
+ - name: Create build environment
+ run: mkdir ${{runner.workspace}}/build
+ - name: Configure
+ working-directory: ${{runner.workspace}}/build
+ run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DQt5_DIR=$(brew --prefix qt5)/lib/cmake/Qt5
+ - name: Make
+ working-directory: ${{runner.workspace}}/build
+ run: |
+ make -j$(sysctl -n hw.ncpu)
+ mkdir dist
+ cp -r melonDS.app dist
+ - uses: actions/upload-artifact@v1
+ with:
+ name: melonDS.app
+ path: ${{runner.workspace}}/build/dist
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 04ad2a58..fcd4741c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,6 +8,8 @@ if (POLICY CMP0076)
cmake_policy(SET CMP0076 NEW)
endif()
+set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version")
+
project(melonDS CXX)
set(CMAKE_C_STANDARD 11)
@@ -100,4 +102,4 @@ add_subdirectory(src)
if (BUILD_QT_SDL)
add_subdirectory(src/frontend/qt_sdl)
-endif()
+endif()
\ No newline at end of file
diff --git a/README.md b/README.md
index 2fb2315a..64489dbb 100644
--- a/README.md
+++ b/README.md
@@ -84,6 +84,21 @@ If everything went well, melonDS and the libraries it needs should now be in the
```
If everything went well, melonDS should now be in the `dist` folder.
+### macOS:
+1. Install the [Homebrew Package Manager](https://brew.sh)
+2. Install dependencies: `brew install git pkg-config cmake sdl2 qt5 libslirp`
+3. Compile:
+ ```zsh
+ git clone https://github.com/Arisotura/melonDS.git
+ cd melonDS
+ mkdir build && cd build
+ cmake .. -DQt5_DIR=$(brew --prefix qt5)/lib/cmake/Qt5
+ make -j$(sysctl -n hw.ncpu)
+ mkdir dist && cp -r melonDS.app dist
+ ```
+If everything went well, melonDS.app should now be in the `dist` folder.
+
+
## TODO LIST
* DSi emulation
diff --git a/melonDS.icns b/melonDS.icns
new file mode 100644
index 00000000..b4f37335
Binary files /dev/null and b/melonDS.icns differ
diff --git a/melonDS.plist b/melonDS.plist
new file mode 100644
index 00000000..1328777e
--- /dev/null
+++ b/melonDS.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ CFBundleExecutable
+ melonDS
+ CFBundleIconFile
+ melonDS.icns
+ CFBundleIdentifier
+ net.kuribo64.melonDS
+ CFBundleDevelopmentRegion
+ English
+ CFBundlePackageType
+ APPL
+ CFBundleVersion
+ 0.9
+ CFBundleShortVersionString
+ 0.9
+ NSHumanReadableCopyright
+ Licensed under GPLv3
+ NSHighResolutionCapable
+
+
+
\ No newline at end of file
diff --git a/src/ARMJIT_Memory.cpp b/src/ARMJIT_Memory.cpp
index 70d18e68..cc0f1493 100644
--- a/src/ARMJIT_Memory.cpp
+++ b/src/ARMJIT_Memory.cpp
@@ -22,7 +22,9 @@
#include "NDSCart.h"
#include "SPU.h"
+#ifndef __APPLE__
#include
+#endif
/*
We're handling fastmem here.
@@ -152,7 +154,12 @@ static void SigsegvHandler(int sig, siginfo_t* info, void* rawContext)
u8* curArea = (u8*)(NDS::CurCPU == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start);
#ifdef __x86_64__
desc.EmulatedFaultAddr = (u8*)info->si_addr - curArea;
- desc.FaultPC = (u8*)context->uc_mcontext.gregs[REG_RIP];
+ #ifdef __APPLE__
+ desc.FaultPC = (u8*)context->uc_mcontext->__ss.__rip;
+ #else
+ desc.FaultPC = (u8*)context->uc_mcontext.gregs[REG_RIP];
+ #endif
+
#else
desc.EmulatedFaultAddr = (u8*)context->uc_mcontext.fault_address - curArea;
desc.FaultPC = (u8*)context->uc_mcontext.pc;
@@ -161,7 +168,11 @@ static void SigsegvHandler(int sig, siginfo_t* info, void* rawContext)
if (ARMJIT_Memory::FaultHandler(desc))
{
#ifdef __x86_64__
- context->uc_mcontext.gregs[REG_RIP] = (u64)desc.FaultPC;
+ #ifdef __APPLE__
+ context->uc_mcontext->__ss.__rip = (u64)desc.FaultPC;
+ #else
+ context->uc_mcontext.gregs[REG_RIP] = (u64)desc.FaultPC;
+ #endif
#else
context->uc_mcontext.pc = (u64)desc.FaultPC;
#endif
@@ -701,7 +712,14 @@ void Init()
FastMem7Start = MemoryBase + AddrSpaceSize;
MemoryBase = MemoryBase + AddrSpaceSize*2;
- MemoryFile = memfd_create("melondsfastmem", 0);
+ #ifdef __APPLE__
+ char* fastmemPidName = new char[snprintf(NULL, 0, "melondsfastmem%d", getpid()) + 1];
+ sprintf(fastmemPidName, "melondsfastmem%d", getpid());
+ MemoryFile = shm_open(fastmemPidName, O_RDWR|O_CREAT, 0600);
+ delete[] fastmemPidName;
+ #else
+ MemoryFile = memfd_create("melondsfastmem", 0);
+ #endif
ftruncate(MemoryFile, MemoryTotalSize);
struct sigaction sa;
@@ -736,6 +754,11 @@ void DeInit()
svcUnmapProcessCodeMemory(envGetOwnProcessHandle(), (u64)MemoryBaseCodeMem, (u64)MemoryBase, MemoryTotalSize);
virtmemFree(MemoryBaseCodeMem, MemoryTotalSize);
free(MemoryBase);
+#elif defined(__APPLE__)
+ char* fastmemPidName = new char[snprintf(NULL, 0, "melondsfastmem%d", getpid()) + 1];
+ sprintf(fastmemPidName, "melondsfastmem%d", getpid());
+ shm_unlink(fastmemPidName);
+ delete[] fastmemPidName;
#elif defined(_WIN32)
assert(UnmapViewOfFile(MemoryBase));
CloseHandle(MemoryFile);
@@ -1259,4 +1282,4 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
return NULL;
}
-}
\ No newline at end of file
+}
diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.cpp b/src/ARMJIT_x64/ARMJIT_Compiler.cpp
index 076f48cf..cc4ad800 100644
--- a/src/ARMJIT_x64/ARMJIT_Compiler.cpp
+++ b/src/ARMJIT_x64/ARMJIT_Compiler.cpp
@@ -221,6 +221,8 @@ Compiler::Compiler()
#ifdef _WIN32
DWORD dummy;
VirtualProtect(pageAligned, alignedSize, PAGE_EXECUTE_READWRITE, &dummy);
+ #elif defined(__APPLE__)
+ pageAligned = (u8*)mmap(NULL, 1024*1024*32, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS ,-1, 0);
#else
mprotect(pageAligned, alignedSize, PROT_EXEC | PROT_READ | PROT_WRITE);
#endif
diff --git a/src/ARMJIT_x64/ARMJIT_Linkage.s b/src/ARMJIT_x64/ARMJIT_Linkage.s
index 0a84df07..8cc0b5f9 100644
--- a/src/ARMJIT_x64/ARMJIT_Linkage.s
+++ b/src/ARMJIT_x64/ARMJIT_Linkage.s
@@ -29,8 +29,13 @@
.p2align 4,,15
+#ifdef __APPLE__
+.global _ARM_Dispatch
+_ARM_Dispatch:
+#else
.global ARM_Dispatch
ARM_Dispatch:
+#endif
#ifdef WIN64
push rdi
push rsi
@@ -54,8 +59,13 @@ ARM_Dispatch:
.p2align 4,,15
+#ifdef __APPLE__
+.global _ARM_Ret
+_ARM_Ret:
+#else
.global ARM_Ret
ARM_Ret:
+#endif
mov [RCPU + ARM_CPSR_offset], RCPSR
#ifdef WIN64
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d6c38971..446480d6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -100,10 +100,17 @@ if (ENABLE_JIT)
endif()
endif()
+if (APPLE)
+ target_include_directories(core PUBLIC /usr/local/include)
+ target_link_directories(core PUBLIC /usr/local/lib)
+endif()
+
if (ENABLE_OGLRENDERER)
if (WIN32)
target_link_libraries(core ole32 comctl32 ws2_32 opengl32)
- else()
+ elseif (APPLE)
+ target_link_libraries(core "-framework OpenGL")
+ else()
target_link_libraries(core GL EGL)
endif()
else()
diff --git a/src/Config.cpp b/src/Config.cpp
index 341b14c3..f7db2528 100644
--- a/src/Config.cpp
+++ b/src/Config.cpp
@@ -73,7 +73,11 @@ ConfigEntry ConfigFile[] =
{"JIT_MaxBlockSize", 0, &JIT_MaxBlockSize, 32, NULL, 0},
{"JIT_BranchOptimisations", 0, &JIT_BranchOptimisations, 1, NULL, 0},
{"JIT_LiteralOptimisations", 0, &JIT_LiteralOptimisations, 1, NULL, 0},
- {"JIT_FastMemory", 0, &JIT_FastMemory, 1, NULL, 0},
+ #ifdef __APPLE__
+ {"JIT_FastMemory", 0, &JIT_FastMemory, 0, NULL, 0},
+ #else
+ {"JIT_FastMemory", 0, &JIT_FastMemory, 1, NULL, 0},
+ #endif
#endif
{"", -1, NULL, 0, NULL, 0}
diff --git a/src/OpenGLSupport.h b/src/OpenGLSupport.h
index 925c0ad0..44c511f5 100644
--- a/src/OpenGLSupport.h
+++ b/src/OpenGLSupport.h
@@ -23,8 +23,13 @@
#include
// TODO: different includes for each platform
-#include
-#include
+#ifdef __APPLE__
+ #include
+ #include
+#else
+ #include
+ #include
+#endif
#include "Platform.h"
@@ -61,6 +66,11 @@
#endif
+#ifdef __APPLE__
+
+#define DO_PROCLIST(func)
+
+#else
#define DO_PROCLIST(func) \
DO_PROCLIST_1_3(func) \
@@ -128,6 +138,7 @@
\
func(GLGETSTRINGI, glGetStringi); \
+#endif
namespace OpenGL
{
diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt
index 9a0a025c..0d695d6e 100644
--- a/src/frontend/qt_sdl/CMakeLists.txt
+++ b/src/frontend/qt_sdl/CMakeLists.txt
@@ -95,6 +95,19 @@ if (PORTABLE)
add_definitions(-DPORTABLE)
endif()
+if (APPLE)
+ set_target_properties(melonDS PROPERTIES
+ MACOSX_BUNDLE true
+ MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/melonDS.plist
+ OUTPUT_NAME melonDS
+ )
+
+ # Copy icon into the bundle
+ target_sources(melonDS PRIVATE "${CMAKE_SOURCE_DIR}/melonDS.icns")
+ set_source_files_properties("${CMAKE_SOURCE_DIR}/melonDS.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
+
+endif()
+
install(FILES ../../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES ../../../icon/melon_16x16.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/16x16/apps RENAME net.kuribo64.melonDS.png)
install(FILES ../../../icon/melon_32x32.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/32x32/apps RENAME net.kuribo64.melonDS.png)
@@ -102,4 +115,4 @@ install(FILES ../../../icon/melon_48x48.png DESTINATION ${CMAKE_INSTALL_PREFIX}/
install(FILES ../../../icon/melon_64x64.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/64x64/apps RENAME net.kuribo64.melonDS.png)
install(FILES ../../../icon/melon_128x128.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/128x128/apps RENAME net.kuribo64.melonDS.png)
install(FILES ../../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/256x256/apps RENAME net.kuribo64.melonDS.png)
-install(TARGETS melonDS RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
+install(TARGETS melonDS BUNDLE DESTINATION ${CMAKE_BINARY_DIR} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.cpp b/src/frontend/qt_sdl/EmuSettingsDialog.cpp
index 79ce5ed0..31831826 100644
--- a/src/frontend/qt_sdl/EmuSettingsDialog.cpp
+++ b/src/frontend/qt_sdl/EmuSettingsDialog.cpp
@@ -65,6 +65,9 @@ EmuSettingsDialog::EmuSettingsDialog(QWidget* parent) : QDialog(parent), ui(new
ui->chkJITBranchOptimisations->setChecked(Config::JIT_BranchOptimisations != 0);
ui->chkJITLiteralOptimisations->setChecked(Config::JIT_LiteralOptimisations != 0);
ui->chkJITFastMemory->setChecked(Config::JIT_FastMemory != 0);
+ #ifdef __APPLE__
+ ui->chkJITFastMemory->setDisabled(true);
+ #endif
ui->spnJITMaximumBlockSize->setValue(Config::JIT_MaxBlockSize);
#else
ui->chkEnableJIT->setDisabled(true);
@@ -329,6 +332,8 @@ void EmuSettingsDialog::on_chkEnableJIT_toggled()
bool disabled = !ui->chkEnableJIT->isChecked();
ui->chkJITBranchOptimisations->setDisabled(disabled);
ui->chkJITLiteralOptimisations->setDisabled(disabled);
- ui->chkJITFastMemory->setDisabled(disabled);
+ #ifndef __APPLE__
+ ui->chkJITFastMemory->setDisabled(disabled);
+ #endif
ui->spnJITMaximumBlockSize->setDisabled(disabled);
}
diff --git a/src/frontend/qt_sdl/InputConfigDialog.cpp b/src/frontend/qt_sdl/InputConfigDialog.cpp
index 9f08731d..eaf1e9bd 100644
--- a/src/frontend/qt_sdl/InputConfigDialog.cpp
+++ b/src/frontend/qt_sdl/InputConfigDialog.cpp
@@ -216,6 +216,7 @@ KeyMapButton::KeyMapButton(int* mapping, bool hotkey) : QPushButton()
setCheckable(true);
setText(mappingText());
+ setFocusPolicy(Qt::StrongFocus); //Fixes binding keys in macOS
connect(this, &KeyMapButton::clicked, this, &KeyMapButton::onClick);
}
diff --git a/src/frontend/qt_sdl/LAN_PCap.cpp b/src/frontend/qt_sdl/LAN_PCap.cpp
index ce278bcb..8138699e 100644
--- a/src/frontend/qt_sdl/LAN_PCap.cpp
+++ b/src/frontend/qt_sdl/LAN_PCap.cpp
@@ -33,7 +33,11 @@
#include
#include
#include
- #include
+ #ifdef __APPLE__
+ #include
+ #else
+ #include
+ #endif
#endif
@@ -66,6 +70,9 @@ const char* PCapLibNames[] =
#ifdef __WIN32__
// TODO: name for npcap in non-WinPCap mode
"wpcap.dll",
+#elif defined(__APPLE__)
+ "libpcap.A.dylib",
+ "libpcap.dylib",
#else
// Linux lib names
"libpcap.so.1",
@@ -276,6 +283,16 @@ bool Init(bool open_adapter)
struct sockaddr_in* sa = (sockaddr_in*)curaddr->ifa_addr;
memcpy(adata->IP_v4, &sa->sin_addr, 4);
}
+ #ifdef __APPLE__
+ else if (af == AF_LINK)
+ {
+ struct sockaddr_dl* sa = (sockaddr_dl*)curaddr->ifa_addr;
+ if (sa->sdl_alen != 6)
+ printf("weird MAC length %d for %s\n", sa->sdl_alen, curaddr->ifa_name);
+ else
+ memcpy(adata->MAC, LLADDR(sa), 6);
+ }
+ #else
else if (af == AF_PACKET)
{
struct sockaddr_ll* sa = (sockaddr_ll*)curaddr->ifa_addr;
@@ -284,7 +301,7 @@ bool Init(bool open_adapter)
else
memcpy(adata->MAC, sa->sll_addr, 6);
}
-
+ #endif
curaddr = curaddr->ifa_next;
}
}