summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Chavez <david@dcvz.io>2022-06-22 20:59:21 +0200
committerGitHub <noreply@github.com>2022-06-22 14:59:21 -0400
commite42b18cf71c828cbab9b2dca4d74c3c554b2acc7 (patch)
tree7f9389fe784ba554232bb15f751dfaf5a925330b
parent77e7080a8cc2b76eddb0bca6a0beeb0685288758 (diff)
Add Support for macOS (#441)
* Fixed soh filters * add more makefile changes * almost ready * more updates * update * update * Update Makefiles to handle both platforms * Allow for overriding the CXX and CC executables * Restore original structure while supporting custom CXX flags * Remove some platform specific libs * Dynamic target name * Make X11 paths package-agnostic * Remove changes to `gfx_opengl.cpp` * Use OpenGL2 on MacOS instead of OpenGL3 * make it actually render something * render at least the first texture, still need to figure out the second one * Let’s use OpenGL 3 again * maybe this works to get the right texture? link's eyes still look off a bit * did this work? * set the platform to macos * actual numbers are right, but logic is ugly XXX/TODO, i know * add zlib to ldflags for ZAPDUtils * A bit of cleanup * Revert unneeded changes * Remove GL_CHECK * Fix issues with z64 branch * use an std::map instead of a giant array * three point filter fix (#2) * Fix mac compilation * fix audio for 64 bit * revert audio heap size, keep bigger pools * Add more Apple specific checks to our modifications * Add building instructions for macOS * Remove unecessary step from building instructions * Add missing SDL2 & GLEW to Linux LDLIBS * Update BUILDING.md Co-authored-by: BountyChocolate123456 <101743444+BountyChocolate123456@users.noreply.github.com> * Update soh/.gitignore to include other arch binaries Co-authored-by: BountyChocolate123456 <101743444+BountyChocolate123456@users.noreply.github.com> * Use right platform name for debugging window Co-authored-by: BountyChocolate123456 <101743444+BountyChocolate123456@users.noreply.github.com> * Fix stormlib on macos (arm64) * Simplify some of the ifdef checks * Revert an older no longer necessary fix * Remove remaining unecessary deviations * Update building instructions after StormLib changes * Feature: Use OpenGL 4.1 (#1) * Further tweak the BUILDING * Tidy up * reword -j message * Add Jenkins CI Support (#2) * Fix type issues * add target <appbundle> and <filledappbundle> add makefile targets to create an .app `filledappbundle` creates the target with the .otr included this should perhaps be moved to Application Support though * pull gcc's rpath from otool output * move make target to the end so it's not default * Add Jenkins and make exe in par with other platforms * Actually save build artefacts * Fix artefact path * Remove x11 mentions and linking (not used) * Update building instructions for generating app * use appsupport directory * Add new app icon * Update target to match macOS types * Update more audio types * fix null deref in Audio_PlayFanfare * Remove old import from z64 * address final nit with apple ifdefs Co-authored-by: KiritoDev <36680385+KiritoDv@users.noreply.github.com> Co-authored-by: Jeffrey Crowell <github@crowell.biz> Co-authored-by: BountyChocolate123456 <101743444+BountyChocolate123456@users.noreply.github.com>
-rw-r--r--.gitignore7
-rw-r--r--BUILDING.md21
-rw-r--r--Jenkinsfile34
-rw-r--r--OTRExporter/OTRExporter/Makefile6
-rw-r--r--StormLib/src/SFileAddFile.cpp2
-rw-r--r--ZAPDTR/Makefile25
-rw-r--r--ZAPDTR/ZAPD/ZRom.cpp6
-rw-r--r--ZAPDTR/ZAPDUtils/Makefile3
-rw-r--r--ZAPDTR/lib/libgfxd/Makefile1
-rw-r--r--libultraship/Makefile17
-rw-r--r--libultraship/libultraship/Audio.cpp36
-rw-r--r--libultraship/libultraship/Audio.h4
-rw-r--r--libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp88
-rw-r--r--libultraship/libultraship/Lib/Fast3D/gfx_pc.h1
-rw-r--r--libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp15
-rw-r--r--libultraship/libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp12
-rw-r--r--libultraship/libultraship/SDLAudioPlayer.h4
-rw-r--r--libultraship/libultraship/SDLController.h4
-rw-r--r--libultraship/libultraship/SohImGuiImpl.cpp6
-rw-r--r--libultraship/libultraship/Window.cpp4
-rw-r--r--soh/.gitignore9
-rw-r--r--soh/Makefile106
-rw-r--r--soh/include/functions.h2
-rw-r--r--soh/include/z64item.h2
-rw-r--r--soh/macosx/Info.plist35
-rw-r--r--soh/macosx/PkgInfo1
-rw-r--r--soh/macosx/appsupport.m26
-rwxr-xr-xsoh/macosx/launcher.sh9
-rw-r--r--soh/macosx/sohIcon.pngbin0 -> 142622 bytes
-rw-r--r--soh/soh/OTRGlobals.cpp5
-rw-r--r--soh/src/buffers/heaps.c2
-rw-r--r--soh/src/code/code_800EC960.c17
32 files changed, 441 insertions, 69 deletions
diff --git a/.gitignore b/.gitignore
index 5fb41fae4..5769df64d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -399,4 +399,9 @@ ZAPDUtils/build/
ZAPD/BuildInfo.h
DebugObj/*
-ReleaseObj/* \ No newline at end of file
+ReleaseObj/*
+.tags
+tags
+oot.otr
+oot_save.sav
+shipofharkinian.ini
diff --git a/BUILDING.md b/BUILDING.md
index 1f9d9fcc5..d6ffb26bf 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -46,6 +46,27 @@ make setup -j$(nproc) OPTFLAGS=-O2 DEBUG=0
make -j $(nproc) OPTFLAGS=-O2 DEBUG=0
```
+## macOS
+
+1. Requires `gcc@12, sdl2, libpng, glew, dylibbundler` (can be installed via brew, etc)
+```bash
+# Clone the repo
+git clone https://github.com/HarbourMasters/Shipwright.git
+cd ShipWright
+# Copy the baserom to the OTRExporter folder
+cp <path to your ROM> OTRExporter
+
+cd soh
+# Extract the assets/Compile the exporter/Run the exporter
+# -jX defines number of cores to use for compilation - lower or remove entirely if having issues
+make setup -j8 DEBUG=0 CC=gcc-12 CXX=g++-12
+# Compile the code (watch the -j parameter as above)
+make -j8 DEBUG=0 CC=gcc-12 CXX=g++-12
+# Create macOS app bundle
+make filledappbundle
+```
+9. Launch soh app in the soh folder!
+
# Compatible Roms
```
OOT_PAL_GC checksum 0x09465AC3
diff --git a/Jenkinsfile b/Jenkinsfile
index 0134b2b5d..a2c4203cc 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -122,5 +122,39 @@ pipeline {
}
}
}
+ stage ('Build macOS') {
+ agent {
+ label "SoH-Mac-Builders"
+ }
+ steps {
+ checkout([
+ $class: 'GitSCM',
+ branches: scm.branches,
+ doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations,
+ extensions: scm.extensions,
+ userRemoteConfigs: scm.userRemoteConfigs
+ ])
+ catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
+ sh '''
+ cp ../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64
+
+ cd soh
+ make setup -j4 DEBUG=0 CC=gcc-12 CXX=g++-12
+ make -j4 DEBUG=0 CC=gcc-12 CXX=g++-12
+
+ make -j4 appbundle
+
+ mv ../README.md readme.txt
+ 7z a soh-mac.7z soh.app readme.txt
+ '''
+ }
+ archiveArtifacts artifacts: 'soh/soh-mac.7z', followSymlinks: false, onlyIfSuccessful: true
+ }
+ post {
+ always {
+ step([$class: 'WsCleanup']) // Clean workspace
+ }
+ }
+ }
}
} \ No newline at end of file
diff --git a/OTRExporter/OTRExporter/Makefile b/OTRExporter/OTRExporter/Makefile
index 0046df18e..c3882b5e3 100644
--- a/OTRExporter/OTRExporter/Makefile
+++ b/OTRExporter/OTRExporter/Makefile
@@ -1,6 +1,6 @@
# Only used for standalone compilation, usually inherits these from the main makefile
-CXX := g++
+CXX ?= g++
AR := ar
FORMAT := clang-format-11
@@ -31,7 +31,7 @@ ifneq ($(LTO),0)
CXXFLAGS += -flto
endif
-SRC_DIRS := $(shell find -type d -not -path "*build*")
+SRC_DIRS := $(shell find . -type d -not -path "*build*")
CXX_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp))
H_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.h))
@@ -69,4 +69,4 @@ build/%.o: %.cpp
$(LIB): $(O_FILES)
$(AR) rcs $@ $^
--include $(D_FILES) \ No newline at end of file
+-include $(D_FILES)
diff --git a/StormLib/src/SFileAddFile.cpp b/StormLib/src/SFileAddFile.cpp
index 1f7156e99..638037a1e 100644
--- a/StormLib/src/SFileAddFile.cpp
+++ b/StormLib/src/SFileAddFile.cpp
@@ -100,7 +100,7 @@ static int FillWritableHandle(
pFileEntry->dwFlags = dwFlags | MPQ_FILE_EXISTS;
// Initialize the file time, CRC32 and MD5
- assert(sizeof(hf->hctx) >= sizeof(hash_state));
+ //assert(sizeof(hf->hctx) >= sizeof(hash_state));
memset(pFileEntry->md5, 0, MD5_DIGEST_SIZE);
md5_init((hash_state *)hf->hctx);
pFileEntry->dwCrc32 = crc32(0, Z_NULL, 0);
diff --git a/ZAPDTR/Makefile b/ZAPDTR/Makefile
index 9ff869f89..2e871b32f 100644
--- a/ZAPDTR/Makefile
+++ b/ZAPDTR/Makefile
@@ -7,12 +7,13 @@ DEBUG ?= 0
COPYCHECK_ARGS ?=
LLD ?= 0
WERROR ?= 0
+UNAME := $(shell uname)
# Use clang++ if available, else use g++
ifeq ($(shell command -v clang++ >/dev/null 2>&1; echo $$?),0)
- CXX := clang++
+ CXX ?= clang++
else
- CXX := g++
+ CXX ?= g++
endif
INC := -I ZAPD -I lib/elfio -I lib/libgfxd -I lib/tinyxml2 -I ZAPDUtils
@@ -44,8 +45,15 @@ ifneq ($(DEPRECATION_ON),0)
endif
# CXXFLAGS += -DTEXTURE_DEBUG
-LDFLAGS := -lm -ldl -lpng \
- -L../StormLib/build -L../libultraship -lz -lbz2 -pthread -lpulse -lultraship -lstorm -lSDL2 -lGLEW -lGL -lX11
+LDFLAGS := -lm -ldl \
+ -L../StormLib/build -L../libultraship -lbz2 -pthread -lultraship -lstorm
+
+ifeq ($(UNAME), Darwin)
+ LDFLAGS += $(shell pkg-config --libs glew libpng zlib) $(shell sdl2-config --libs) -framework OpenGL
+ INC += $(shell pkg-config --cflags libpng)
+else
+ LDFLAGS += -lpng -lGL -lGLEW -lX11 -lz -lSDL2 -lpulse
+endif
# Use LLD if available. Set LLD=0 to not use it
ifeq ($(shell command -v ld.lld >/dev/null 2>&1; echo $$?),0)
@@ -56,21 +64,12 @@ ifneq ($(LLD),0)
LDFLAGS += -fuse-ld=lld
endif
-UNAME := $(shell uname)
UNAMEM := $(shell uname -m)
ifneq ($(UNAME), Darwin)
LDFLAGS += -Wl,-export-dynamic -lstdc++fs
EXPORTERS := -Wl,--whole-archive ../OTRExporter/OTRExporter/OTRExporter.a -Wl,--no-whole-archive
else
EXPORTERS := -Wl,-force_load ../OTRExporter/OTRExporter/OTRExporter.a
- ifeq ($(UNAMEM),arm64)
- ifeq ($(shell brew list libpng > /dev/null 2>&1; echo $$?),0)
- LDFLAGS += -L $(shell brew --prefix)/lib
- INC += -I $(shell brew --prefix)/include
- else
- $(error Please install libpng via Homebrew)
- endif
- endif
endif
diff --git a/ZAPDTR/ZAPD/ZRom.cpp b/ZAPDTR/ZAPD/ZRom.cpp
index 111888e86..f13a6e2f8 100644
--- a/ZAPDTR/ZAPD/ZRom.cpp
+++ b/ZAPDTR/ZAPD/ZRom.cpp
@@ -4,7 +4,7 @@
#include "Utils/Directory.h"
#include "yaz0/yaz0.h"
-#ifndef _MSC_VER
+#ifdef __linux__
#include <byteswap.h>
#endif
#include <Globals.h>
@@ -17,6 +17,10 @@ namespace fs = std::filesystem;
#define __bswap_32 _byteswap_ulong
#define bswap_32 _byteswap_ulong
#endif
+#if defined __APPLE__
+#define __bswap32 __builtin_bswap32
+#define bswap32 __builtin_bswap32
+#endif
// ROM DMA Table Start
#define OOT_OFF_NTSC_10_RC 0x7430
diff --git a/ZAPDTR/ZAPDUtils/Makefile b/ZAPDTR/ZAPDUtils/Makefile
index aef678031..b9c4e29ad 100644
--- a/ZAPDTR/ZAPDUtils/Makefile
+++ b/ZAPDTR/ZAPDUtils/Makefile
@@ -1,7 +1,8 @@
# Only used for standalone compilation, usually inherits these from the main makefile
+CXX ?= g++
CXXFLAGS ?= -Wall -Wextra -O2 -g -std=c++17
-SRC_DIRS := $(shell find -type d -not -path "*build*")
+SRC_DIRS := $(shell find . -type d -not -path "*build*")
CPP_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp))
H_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.h))
diff --git a/ZAPDTR/lib/libgfxd/Makefile b/ZAPDTR/lib/libgfxd/Makefile
index b340ff5c0..5c3edbef4 100644
--- a/ZAPDTR/lib/libgfxd/Makefile
+++ b/ZAPDTR/lib/libgfxd/Makefile
@@ -1,3 +1,4 @@
+CC ?= gcc
CFLAGS = -Wall -O2 -g
UC_OBJ = uc_f3d.o uc_f3db.o uc_f3dex.o uc_f3dexb.o uc_f3dex2.o
OBJ = gfxd.o $(UC_OBJ)
diff --git a/libultraship/Makefile b/libultraship/Makefile
index d5879e026..d894514b6 100644
--- a/libultraship/Makefile
+++ b/libultraship/Makefile
@@ -1,9 +1,10 @@
# Only used for standalone compilation, usually inherits these from the main makefile
-CXX := g++
-CC := gcc
+CXX ?= g++
+CC ?= gcc
AR := ar
FORMAT := clang-format-11
+UNAME := $(shell uname)
ASAN ?= 0
DEBUG ?= 1
@@ -16,7 +17,8 @@ WARN := -Wall -Wextra -Werror \
-Wno-unused-function \
-Wno-parentheses \
-Wno-narrowing \
- -Wno-missing-field-initializers
+ -Wno-missing-field-initializers \
+ -Wno-error=multichar
CWARN :=
CXXWARN := -Wno-deprecated-enum-enum-conversion
@@ -25,6 +27,10 @@ CXXFLAGS := $(WARN) $(CXXWARN) -std=c++20 -D_GNU_SOURCE -DENABLE_OPENGL -DSPDLOG
CFLAGS := $(WARN) $(CWARN) -std=c99 -D_GNU_SOURCE -DENABLE_OPENGL -DSPDLOG_ACTIVE_LEVEL=0
CPPFLAGS := -MMD
+ifeq ($(UNAME), Darwin) #APPLE
+ CPPFLAGS += $(shell pkg-config --cflags sdl2 glew) -framework OpenGL
+endif
+
ifneq ($(DEBUG),0)
CXXFLAGS += -g -D_DEBUG
CFLAGS += -g -D_DEBUG
@@ -40,7 +46,7 @@ ifneq ($(LTO),0)
CFLAGS += -flto
endif
-SRC_DIRS := $(shell find -type d -not -path "*build*")
+SRC_DIRS := $(shell find . -type d -not -path "*build*")
CXX_FILES := \
$(shell find libultraship/Factories -name "*.cpp") \
@@ -71,6 +77,7 @@ INC_DIRS := $(addprefix -I, \
libultraship/Lib/Fast3D/U64 \
libultraship/Lib/spdlog \
libultraship/Lib/spdlog/include \
+ libultraship/Lib/ImGui \
libultraship \
../StormLib/src \
)
@@ -97,4 +104,4 @@ build/%.o: %.c
$(LIB): $(O_FILES)
$(AR) rcs $@ $^
--include $(D_FILES) \ No newline at end of file
+-include $(D_FILES)
diff --git a/libultraship/libultraship/Audio.cpp b/libultraship/libultraship/Audio.cpp
index 6510a471e..6afe90c53 100644
--- a/libultraship/libultraship/Audio.cpp
+++ b/libultraship/libultraship/Audio.cpp
@@ -8,20 +8,20 @@ namespace Ship
ResourceFile::ParseFileBinary(reader, res);
- int seqDataSize = reader->ReadInt32();
+ uint32_t seqDataSize = reader->ReadInt32();
seq->seqData.reserve(seqDataSize);
- for (int i = 0; i < seqDataSize; i++)
+ for (uint32_t i = 0; i < seqDataSize; i++)
seq->seqData.push_back(reader->ReadUByte());
seq->seqNumber = reader->ReadUByte();
seq->medium = reader->ReadUByte();
seq->cachePolicy = reader->ReadUByte();
- int numFonts = reader->ReadInt32();
+ uint32_t numFonts = reader->ReadInt32();
- for (int i = 0; i < numFonts; i++)
+ for (uint32_t i = 0; i < numFonts; i++)
seq->fonts.push_back(reader->ReadUByte());
}
@@ -36,26 +36,26 @@ namespace Ship
entry->unk_bit26 = reader->ReadByte();
entry->unk_bit25 = reader->ReadByte();
- int dataSize = reader->ReadInt32();
+ uint32_t dataSize = reader->ReadInt32();
- for (int i = 0; i < dataSize; i++)
+ for (uint32_t i = 0; i < dataSize; i++)
entry->data.push_back(reader->ReadUByte());
entry->loop.start = reader->ReadUInt32();
entry->loop.end = reader->ReadUInt32();
entry->loop.count = reader->ReadUInt32();
- int loopStateCnt = reader->ReadUInt32();
+ uint32_t loopStateCnt = reader->ReadUInt32();
- for (int i = 0; i < loopStateCnt; i++)
+ for (uint32_t i = 0; i < loopStateCnt; i++)
entry->loop.states.push_back(reader->ReadInt16());
entry->book.order = reader->ReadInt32();
entry->book.npredictors = reader->ReadInt32();
- int bookSize = reader->ReadInt32();
+ uint32_t bookSize = reader->ReadInt32();
- for (int i = 0; i < bookSize; i++)
+ for (uint32_t i = 0; i < bookSize; i++)
entry->book.books.push_back(reader->ReadInt16());
}
@@ -72,11 +72,11 @@ namespace Ship
soundFont->data2 = reader->ReadInt16();
soundFont->data3 = reader->ReadInt16();
- int drumCnt = reader->ReadInt32();
- int instrumentCnt = reader->ReadInt32();
- int sfxCnt = reader->ReadInt32();
+ uint32_t drumCnt = reader->ReadInt32();
+ uint32_t instrumentCnt = reader->ReadInt32();
+ uint32_t sfxCnt = reader->ReadInt32();
- for (int i = 0; i < drumCnt; i++)
+ for (uint32_t i = 0; i < drumCnt; i++)
{
DrumEntry drum;
drum.releaseRate = reader->ReadUByte();
@@ -92,7 +92,7 @@ namespace Ship
soundFont->drums.push_back(drum);
}
- for (int i = 0; i < instrumentCnt; i++)
+ for (uint32_t i = 0; i < instrumentCnt; i++)
{
InstrumentEntry entry;
@@ -143,7 +143,7 @@ namespace Ship
soundFont->instruments.push_back(entry);
}
- for (int i = 0; i < sfxCnt; i++)
+ for (uint32_t i = 0; i < sfxCnt; i++)
{
SoundFontEntry* entry = new SoundFontEntry();
@@ -164,9 +164,9 @@ namespace Ship
{
std::vector<AdsrEnvelope*> envelopes;
- int envelopeCnt = reader->ReadInt32();
+ uint32_t envelopeCnt = reader->ReadInt32();
- for (int i = 0; i < envelopeCnt; i++)
+ for (uint32_t i = 0; i < envelopeCnt; i++)
{
AdsrEnvelope* env = new AdsrEnvelope();
env->delay = reader->ReadInt16();
diff --git a/libultraship/libultraship/Audio.h b/libultraship/libultraship/Audio.h
index a63035e50..8c32af744 100644
--- a/libultraship/libultraship/Audio.h
+++ b/libultraship/libultraship/Audio.h
@@ -15,8 +15,8 @@ namespace Ship
struct AdpcmBook
{
- /* 0x00 */ int32_t order;
- /* 0x04 */ int32_t npredictors;
+ /* 0x00 */ uint32_t order;
+ /* 0x04 */ uint32_t npredictors;
/* 0x08 */ std::vector<int16_t> books; // size 8 * order * npredictors. 8-byte aligned
};
diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp
index b2db3186a..83f4904f6 100644
--- a/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp
+++ b/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp
@@ -27,6 +27,9 @@
#include "SDL.h"
#define GL_GLEXT_PROTOTYPES 1
#include "SDL_opengl.h"
+#elif __APPLE__
+#include <SDL.h>
+#include <GL/glew.h>
#else
#include <SDL2/SDL.h>
#include <GL/glew.h>
@@ -67,6 +70,9 @@ struct Framebuffer {
static map<pair<uint64_t, uint32_t>, struct ShaderProgram> shader_program_pool;
static GLuint opengl_vbo;
+#ifdef __APPLE__
+static GLuint opengl_vao;
+#endif
static bool current_depth_mask;
static uint32_t frame_count;
@@ -220,37 +226,67 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
size_t num_floats = 4;
// Vertex shader
+#ifdef __APPLE__
+ append_line(vs_buf, &vs_len, "#version 410 core");
+ append_line(vs_buf, &vs_len, "in vec4 aVtxPos;");
+#else
append_line(vs_buf, &vs_len, "#version 110");
append_line(vs_buf, &vs_len, "attribute vec4 aVtxPos;");
+#endif
for (int i = 0; i < 2; i++) {
if (cc_features.used_textures[i]) {
+ #ifdef __APPLE__
+ vs_len += sprintf(vs_buf + vs_len, "in vec2 aTexCoord%d;\n", i);
+ vs_len += sprintf(vs_buf + vs_len, "out vec2 vTexCoord%d;\n", i);
+ #else
vs_len += sprintf(vs_buf + vs_len, "attribute vec2 aTexCoord%d;\n", i);
vs_len += sprintf(vs_buf + vs_len, "varying vec2 vTexCoord%d;\n", i);
+ #endif
num_floats += 2;
for (int j = 0; j < 2; j++) {
if (cc_features.clamp[i][j]) {
+ #ifdef __APPLE__
+ vs_len += sprintf(vs_buf + vs_len, "in float aTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
+ vs_len += sprintf(vs_buf + vs_len, "out float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
+ #else
vs_len += sprintf(vs_buf + vs_len, "attribute float aTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
vs_len += sprintf(vs_buf + vs_len, "varying float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
+ #endif
num_floats += 1;
}
}
}
}
if (cc_features.opt_fog) {
+ #ifdef __APPLE__
+ append_line(vs_buf, &vs_len, "in vec4 aFog;");
+ append_line(vs_buf, &vs_len, "out vec4 vFog;");
+ #else
append_line(vs_buf, &vs_len, "attribute vec4 aFog;");
append_line(vs_buf, &vs_len, "varying vec4 vFog;");
+ #endif
num_floats += 4;
}
if (cc_features.opt_grayscale) {
+ #ifdef __APPLE__
+ append_line(vs_buf, &vs_len, "in vec4 aGrayscaleColor;");
+ append_line(vs_buf, &vs_len, "out vec4 vGrayscaleColor;");
+ #else
append_line(vs_buf, &vs_len, "attribute vec4 aGrayscaleColor;");
append_line(vs_buf, &vs_len, "varying vec4 vGrayscaleColor;");
+ #endif
num_floats += 4;
}
for (int i = 0; i < cc_features.num_inputs; i++) {
+ #ifdef __APPLE__
+ vs_len += sprintf(vs_buf + vs_len, "in vec%d aInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
+ vs_len += sprintf(vs_buf + vs_len, "out vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
+ #else
vs_len += sprintf(vs_buf + vs_len, "attribute vec%d aInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
vs_len += sprintf(vs_buf + vs_len, "varying vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
+ #endif
num_floats += cc_features.opt_alpha ? 4 : 3;
}
append_line(vs_buf, &vs_len, "void main() {");
@@ -277,26 +313,50 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
append_line(vs_buf, &vs_len, "}");
// Fragment shader
- append_line(fs_buf, &fs_len, "#version 130");
+#ifdef __APPLE__
+ append_line(fs_buf, &fs_len, "#version 410 core");
+#else
+ append_line(fs_buf, &fs_len, "#version 120");
+#endif
//append_line(fs_buf, &fs_len, "precision mediump float;");
for (int i = 0; i < 2; i++) {
if (cc_features.used_textures[i]) {
+ #ifdef __APPLE__
+ fs_len += sprintf(fs_buf + fs_len, "in vec2 vTexCoord%d;\n", i);
+ #else
fs_len += sprintf(fs_buf + fs_len, "varying vec2 vTexCoord%d;\n", i);
+ #endif
for (int j = 0; j < 2; j++) {
if (cc_features.clamp[i][j]) {
+ #ifdef __APPLE__
+ fs_len += sprintf(fs_buf + fs_len, "in float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
+ #else
fs_len += sprintf(fs_buf + fs_len, "varying float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
+ #endif
}
}
}
}
if (cc_features.opt_fog) {
+ #ifdef __APPLE__
+ append_line(fs_buf, &fs_len, "in vec4 vFog;");
+ #else
append_line(fs_buf, &fs_len, "varying vec4 vFog;");
+ #endif
}
if (cc_features.opt_grayscale) {
+ #ifdef __APPLE__
+ append_line(fs_buf, &fs_len, "in vec4 vGrayscaleColor;");
+ #else
append_line(fs_buf, &fs_len, "varying vec4 vGrayscaleColor;");
+ #endif
}
for (int i = 0; i < cc_features.num_inputs; i++) {
+ #ifdef __APPLE__
+ fs_len += sprintf(fs_buf + fs_len, "in vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
+ #else
fs_len += sprintf(fs_buf + fs_len, "varying vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
+ #endif
}
if (cc_features.used_textures[0]) {
append_line(fs_buf, &fs_len, "uniform sampler2D uTex0;");
@@ -316,7 +376,11 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
}
if (current_filter_mode == THREE_POINT) {
+ #if __APPLE__
+ append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture(tex, texCoord - (off)/texSize)");
+ #else
append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture2D(tex, texCoord - (off)/texSize)");
+ #endif
append_line(fs_buf, &fs_len, "vec4 filter3point(in sampler2D tex, in vec2 texCoord, in vec2 texSize) {");
append_line(fs_buf, &fs_len, " vec2 offset = fract(texCoord*texSize - vec2(0.5));");
append_line(fs_buf, &fs_len, " offset -= step(1.0, offset.x + offset.y);");
@@ -330,10 +394,18 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
append_line(fs_buf, &fs_len, "}");
} else {
append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize) {");
+ #if __APPLE__
+ append_line(fs_buf, &fs_len, " return texture(tex, uv);");
+ #else
append_line(fs_buf, &fs_len, " return texture2D(tex, uv);");
+ #endif
append_line(fs_buf, &fs_len, "}");
}
+#if __APPLE__
+ append_line(fs_buf, &fs_len, "out vec4 outColor;");
+#endif
+
append_line(fs_buf, &fs_len, "void main() {");
for (int i = 0; i < 2; i++) {
@@ -405,9 +477,17 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
if (cc_features.opt_invisible) {
append_line(fs_buf, &fs_len, "texel.a = 0.0;");
}
+ #if __APPLE__
+ append_line(fs_buf, &fs_len, "outColor = texel;");
+ #else
append_line(fs_buf, &fs_len, "gl_FragColor = texel;");
+ #endif
} else {
+ #if __APPLE__
+ append_line(fs_buf, &fs_len, "outColor = vec4(texel, 1.0);");
+ #else
append_line(fs_buf, &fs_len, "gl_FragColor = vec4(texel, 1.0);");
+ #endif
}
append_line(fs_buf, &fs_len, "}");
@@ -557,7 +637,6 @@ static void gfx_opengl_select_texture(int tile, GLuint texture_id) {
glActiveTexture(GL_TEXTURE0 + tile);
glBindTexture(GL_TEXTURE_2D, texture_id);
}
-
static void gfx_opengl_upload_texture(const uint8_t *rgba32_buf, uint32_t width, uint32_t height) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba32_buf);
}
@@ -636,6 +715,11 @@ static void gfx_opengl_init(void) {
glGenBuffers(1, &opengl_vbo);
glBindBuffer(GL_ARRAY_BUFFER, opengl_vbo);
+#ifdef __APPLE__
+ glGenVertexArrays(1, &opengl_vao);
+ glBindVertexArray(opengl_vao);
+#endif
+
glEnable(GL_DEPTH_CLAMP);
glDepthFunc(GL_LEQUAL);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.h b/libultraship/libultraship/Lib/Fast3D/gfx_pc.h
index 3be10a016..34fc4fcc4 100644
--- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.h
+++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.h
@@ -2,6 +2,7 @@
#define GFX_PC_H
#include <stdbool.h>
+#include <stddef.h>
#include <stdint.h>
#include <unordered_map>
#include <list>
diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp
index 42ffd69eb..87940a1a3 100644
--- a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp
+++ b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp
@@ -13,6 +13,8 @@
#include "SDL.h"
#define GL_GLEXT_PROTOTYPES 1
#include "SDL_opengl.h"
+#elif __APPLE__
+#include <SDL.h>
#else
#include <SDL2/SDL.h>
#define GL_GLEXT_PROTOTYPES 1
@@ -119,7 +121,7 @@ static void set_fullscreen(bool on, bool call_callback) {
}
static uint64_t previous_time;
-#ifndef __linux__
+#ifdef _WIN32
static HANDLE timer;
#endif
@@ -134,7 +136,14 @@ static void gfx_sdl_init(const char *game_name, bool start_in_fullscreen) {
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-#ifndef __linux
+#if defined(__APPLE__)
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+#endif
+
+#ifdef _WIN32
timer = CreateWaitableTimer(nullptr, false, nullptr);
#endif
@@ -271,7 +280,7 @@ static inline void sync_framerate_with_timer(void) {
const int64_t next = previous_time + 10 * FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR;
const int64_t left = next - t;
if (left > 0) {
-#ifdef __linux__
+#if defined __linux__ || defined __APPLE__
const timespec spec = { 0, left * 100 };
nanosleep(&spec, nullptr);
#else
diff --git a/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp b/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp
index 61e6d99ac..0681a268b 100644
--- a/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp
+++ b/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp
@@ -66,11 +66,15 @@
// SDL
// (the multi-viewports feature requires SDL features supported from SDL 2.0.4+. SDL 2.0.5+ is highly recommended)
+#if defined(__APPLE__)
+#include "SDL.h"
+#include "SDL_syswm.h"
+#include "SDL_stdinc.h"
+#include <TargetConditionals.h>
+#else
#include <SDL2/SDL.h>
#include <SDL2/SDL_syswm.h>
#include <SDL2/SDL_stdinc.h>
-#if defined(__APPLE__)
-#include <TargetConditionals.h>
#endif
#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)
@@ -865,7 +869,11 @@ static void ImGui_ImplSDL2_SwapBuffers(ImGuiViewport* viewport, void*)
// Vulkan support (the Vulkan renderer needs to call a platform-side support function to create the surface)
// SDL is graceful enough to _not_ need <vulkan/vulkan.h> so we can safely include this.
#if SDL_HAS_VULKAN
+#if defined(__APPLE__)
+#include "SDL_vulkan.h"
+#else
#include <SDL2/SDL_vulkan.h>
+#endif
static int ImGui_ImplSDL2_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_instance, const void* vk_allocator, ImU64* out_vk_surface)
{
ImGui_ImplSDL2_ViewportData* vd = (ImGui_ImplSDL2_ViewportData*)viewport->PlatformUserData;
diff --git a/libultraship/libultraship/SDLAudioPlayer.h b/libultraship/libultraship/SDLAudioPlayer.h
index 05e4befd3..0bb6d3665 100644
--- a/libultraship/libultraship/SDLAudioPlayer.h
+++ b/libultraship/libultraship/SDLAudioPlayer.h
@@ -1,6 +1,10 @@
#pragma once
#include "AudioPlayer.h"
+#if __APPLE__
+#include <SDL.h>
+#else
#include <SDL2/SDL.h>
+#endif
namespace Ship {
class SDLAudioPlayer : public AudioPlayer {
diff --git a/libultraship/libultraship/SDLController.h b/libultraship/libultraship/SDLController.h
index fbffa478f..2493efbbc 100644
--- a/libultraship/libultraship/SDLController.h
+++ b/libultraship/libultraship/SDLController.h
@@ -1,6 +1,10 @@
#pragma once
#include "Controller.h"
+#if __APPLE__
+#include <SDL.h>
+#else
#include <SDL2/SDL.h>
+#endif
#define INVALID_SDL_CONTROLLER_GUID (std::string("00000000000000000000000000000000"))
diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp
index 674d4970d..41e8b9a81 100644
--- a/libultraship/libultraship/SohImGuiImpl.cpp
+++ b/libultraship/libultraship/SohImGuiImpl.cpp
@@ -137,7 +137,11 @@ namespace SohImGui {
void ImGuiBackendInit() {
switch (impl.backend) {
case Backend::SDL:
+ #if defined(__APPLE__)
+ ImGui_ImplOpenGL3_Init("#version 410 core");
+ #else
ImGui_ImplOpenGL3_Init("#version 120");
+ #endif
break;
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
@@ -1327,6 +1331,8 @@ namespace SohImGui {
#ifdef _WIN32
ImGui::Text("Platform: Windows");
+#elif __APPLE__
+ ImGui::Text("Platform: macOS");
#else
ImGui::Text("Platform: Linux");
#endif
diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp
index d82f25e56..82506bd1e 100644
--- a/libultraship/libultraship/Window.cpp
+++ b/libultraship/libultraship/Window.cpp
@@ -18,7 +18,11 @@
#include "Lib/Fast3D/gfx_sdl.h"
#include "Lib/Fast3D/gfx_opengl.h"
#include "stox.h"
+#if __APPLE__
+#include <SDL.h>
+#else
#include <SDL2/SDL.h>
+#endif
#include <map>
#include <string>
#include <chrono>
diff --git a/soh/.gitignore b/soh/.gitignore
index 5920cfba7..3c7bcce33 100644
--- a/soh/.gitignore
+++ b/soh/.gitignore
@@ -18,12 +18,16 @@ notes/
baserom/
docs/doxygen/
*.elf
+*-arm64
+*-x86_64
*.sra
*.z64
*.n64
*.v64
*.map
*.dump
+*.app/
+*.icns
out.txt
shipofharkinian.ini
imgui.ini
@@ -404,4 +408,7 @@ ZAPD/BuildInfo.h
cvars.cfg
DebugObj/*
-ReleaseObj/* \ No newline at end of file
+ReleaseObj/*
+
+# Junk from App Bundle
+appsupport
diff --git a/soh/Makefile b/soh/Makefile
index 70670f201..43140dc95 100644
--- a/soh/Makefile
+++ b/soh/Makefile
@@ -1,9 +1,11 @@
-CXX := g++
-CC := gcc
+CXX ?= g++
+CC ?= gcc
LD := lld
AR := ar
FORMAT := clang-format-11
ZAPD := ../ZAPDTR/ZAPD.out
+UNAME := $(shell uname)
+UNAMEM := $(shell uname -m)
LIBULTRASHIP := ../libultraship/libultraship.a
ZAPDUTILS := ../ZAPDTR/ZAPDUtils/ZAPDUtils.a
@@ -17,11 +19,22 @@ LTO ?= 0
WARN := \
-Wno-return-type \
-funsigned-char \
- -mhard-float -fno-stack-protector -fno-common -fno-zero-initialized-in-bss -fno-strict-aliasing -fno-inline-functions -fno-inline-small-functions -fno-toplevel-reorder -ffreestanding -fwrapv \
+ -fno-stack-protector -fno-common -fno-zero-initialized-in-bss -fno-strict-aliasing -fno-inline-functions -fno-inline-small-functions -fno-toplevel-reorder -ffreestanding -fwrapv \
-CXXFLAGS := $(WARN) -std=c++20 -D_GNU_SOURCE -fpermissive -no-pie -nostdlib -msse2 -mfpmath=sse
-CFLAGS := $(WARN) -std=c99 -D_GNU_SOURCE -no-pie -nostdlib -msse2 -mfpmath=sse
+CXXFLAGS := $(WARN) -std=c++20 -D_GNU_SOURCE -fpermissive -no-pie -nostdlib
+CFLAGS := $(WARN) -std=c99 -D_GNU_SOURCE -no-pie -nostdlib
LDFLAGS :=
+
+ifeq ($(UNAME), Linux) #LINUX
+ CXXFLAGS += -mhard-float -msse2 -mfpmath=sse
+ CFLAGS += -mhard-float -msse2 -mfpmath=sse
+endif
+
+ifeq ($(UNAME), Darwin) #APPLE
+ CXXFLAGS += $(shell pkg-config --cflags sdl2) $(shell sdl2-config --cflags) $(shell pkg-config --cflags glew) -framework OpenGL
+ CFLAGS += $(shell pkg-config --cflags sdl2) $(shell sdl2-config --cflags) $(shell pkg-config --cflags glew) -framework OpenGL
+endif
+
CPPFLAGS := -MMD
ifneq ($(DEBUG),0)
@@ -41,7 +54,13 @@ ifneq ($(LTO),0)
LDFLAGS += -flto
endif
+ifeq ($(UNAME), Linux) #LINUX
TARGET := soh.elf
+endif
+
+ifeq ($(UNAME), Darwin) #APPLE
+TARGET := soh-$(UNAMEM)
+endif
INC_DIRS := $(addprefix -I, \
. \
@@ -56,26 +75,52 @@ INC_DIRS := $(addprefix -I, \
../libultraship/libultraship/Lib/Fast3D/U64/PR \
)
+ifeq ($(UNAME), Linux) #LINUX
+ INC_DIRS += $(addprefix -I, \
+ /opt/X11/include \
+)
+endif
+
LDDIRS := $(addprefix -L, \
../libultraship/ \
)
+ifeq ($(UNAME), Linux) #LINUX
+ LDDIRS += $(addprefix -L, \
+ /opt/X11/lib \
+)
+endif
+
LDLIBS := \
$(ZAPDUTILS) \
$(LIBSTORM) \
$(addprefix -l, \
- X11 \
dl \
bz2 \
z \
pthread \
atomic \
+ ultraship \
+)
+
+ifeq ($(UNAME), Linux) #LINUX
+LDLIBS += \
+ $(addprefix -l, \
+ X11 \
SDL2 \
GL \
GLEW \
- pulse\
- ultraship \
+ pulse \
+)
+endif
+
+ifeq ($(UNAME), Darwin) #APPLE
+LDLIBS += \
+ $(addprefix -framework, \
+ OpenGL \
) \
+ $(shell sdl2-config --libs) $(shell pkg-config --libs glew)
+endif
ASSET_BIN_DIRS := $(shell find assets/* -type d -not -path "assets/xml*")
ASSET_FILES_XML := $(foreach dir,$(ASSET_BIN_DIRS),$(wildcard $(dir)/*.xml))
@@ -114,6 +159,14 @@ O_FILES := \
$(CXX_FILES:%.cpp=build/%.o)
D_FILES := $(O_FILES:%.o=%.d)
+# Apple App Bundle
+APPNAME=soh
+APPBUNDLE=$(APPNAME).app
+APPBUNDLECONTENTS=$(APPBUNDLE)/Contents
+APPBUNDLEEXE=$(APPBUNDLECONTENTS)/MacOS
+APPBUNDLERESOURCES=$(APPBUNDLECONTENTS)/Resources
+APPBUNDLEICON=$(APPBUNDLECONTENTS)/Resources
+
# create build directory
SRC_DIRS := $(shell find . -type d -a -not -path "*build*")
$(shell mkdir -p $(SRC_DIRS:%=build/%))
@@ -157,4 +210,39 @@ $(TARGET): $(LIBULTRASHIP)
$(TARGET): $(O_FILES)
$(CXX) $^ -o $@ $(LDFLAGS) -fuse-ld=$(LD) $(LDDIRS) $(LDLIBS)
--include $(D_FILES) \ No newline at end of file
+-include $(D_FILES)
+
+appbundle: macosx/$(APPNAME).icns
+ rm -rf $(APPBUNDLE)
+ mkdir $(APPBUNDLE)
+ mkdir $(APPBUNDLE)/Contents
+ mkdir $(APPBUNDLE)/Contents/MacOS
+ mkdir $(APPBUNDLE)/Contents/Resources
+ cp macosx/Info.plist $(APPBUNDLECONTENTS)/
+ cp macosx/PkgInfo $(APPBUNDLECONTENTS)/
+ cp macosx/$(APPNAME).icns $(APPBUNDLEICON)/
+ cp $(TARGET) $(APPBUNDLEEXE)/soh
+ cp macosx/launcher.sh $(APPBUNDLEEXE)/launcher.sh
+ clang -ObjC macosx/appsupport.m -arch arm64 -arch x86_64 -framework Foundation -o macosx/appsupport
+ cp macosx/appsupport $(APPBUNDLEEXE)/appsupport
+ otool -l $(TARGET) | grep -A 2 LC_RPATH | tail -n 1 | awk '{print $2}' | dylibbundler -od -b -x $(APPBUNDLEEXE)/soh -d $(APPBUNDLECONTENTS)/libs
+
+macosx/$(APPNAME).icns: macosx/$(APPNAME)Icon.png
+ rm -rf macosx/$(APPNAME).iconset
+ mkdir macosx/$(APPNAME).iconset
+ sips -z 16 16 macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_16x16.png
+ sips -z 32 32 macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_16x16@2x.png
+ sips -z 32 32 macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_32x32.png
+ sips -z 64 64 macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_32x32@2x.png
+ sips -z 128 128 macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_128x128.png
+ sips -z 256 256 macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_128x128@2x.png
+ sips -z 256 256 macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_256x256.png
+ sips -z 512 512 macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_256x256@2x.png
+ sips -z 512 512 macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_512x512.png
+ cp macosx/$(APPNAME)Icon.png macosx/$(APPNAME).iconset/icon_512x512@2x.png
+ iconutil -c icns -o macosx/$(APPNAME).icns macosx/$(APPNAME).iconset
+ rm -r macosx/$(APPNAME).iconset
+
+filledappbundle: appbundle
+ cp ./oot.otr $(APPBUNDLEEXE)/oot.otr
+
diff --git a/soh/include/functions.h b/soh/include/functions.h
index 955a47a58..78986cc85 100644
--- a/soh/include/functions.h
+++ b/soh/include/functions.h
@@ -60,7 +60,9 @@ void Locale_ResetRegion(void);
u32 func_80001F48(void);
u32 func_80001F8C(void);
u32 Locale_IsRegionNative(void);
+#ifndef __APPLE__
void __assert(const char* exp, const char* file, s32 line);
+#endif
void isPrintfInit(void);
void osSyncPrintfUnused(const char* fmt, ...);
//void osSyncPrintf(const char* fmt, ...);
diff --git a/soh/include/z64item.h b/soh/include/z64item.h
index 6cb5ec2a4..b42a2efc9 100644
--- a/soh/include/z64item.h
+++ b/soh/include/z64item.h
@@ -501,7 +501,7 @@ typedef enum {
/* 0x72 */ GID_BULLET_BAG_50,
/* 0x73 */ GID_SWORD_KOKIRI,
/* 0x74 */ GID_SKULL_TOKEN_2,
- /* 0x75 */ GID_MAX
+ /* 0x75 */ GID_MAXIMUM
} GetItemDrawID;
typedef enum {
diff --git a/soh/macosx/Info.plist b/soh/macosx/Info.plist
new file mode 100644
index 000000000..af3ea4de5
--- /dev/null
+++ b/soh/macosx/Info.plist
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleName</key>
+ <string>Ship of Harkinian</string>
+ <key>CFBundleExecutable</key>
+ <string>launcher.sh</string>
+ <key>CFBundleGetInfoString</key>
+ <string>2.0.0</string>
+ <key>CFBundleIconFile</key>
+ <string>soh.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.shipofharkinian.ShipOfHarkinian</string>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ </array>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>2.0.0</string>
+ <key>CFBundleSignature</key>
+ <string>ZOoT</string>
+ <key>CFBundleVersion</key>
+ <string>2.0.0</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright 2022 HarbourMasters.</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>10.3</string>
+</dict>
+</plist>
diff --git a/soh/macosx/PkgInfo b/soh/macosx/PkgInfo
new file mode 100644
index 000000000..8f7d36643
--- /dev/null
+++ b/soh/macosx/PkgInfo
@@ -0,0 +1 @@
+APPLZOoT
diff --git a/soh/macosx/appsupport.m b/soh/macosx/appsupport.m
new file mode 100644
index 000000000..a7df45e67
--- /dev/null
+++ b/soh/macosx/appsupport.m
@@ -0,0 +1,26 @@
+#import <Foundation/Foundation.h>
+int main(void) {
+ NSString *appSupportDir = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) lastObject];
+ //If there isn't an App Support Directory yet ...
+ if (![[NSFileManager defaultManager] fileExistsAtPath:appSupportDir isDirectory:NULL]) {
+ NSError *error = nil;
+ //Create one
+ if (![[NSFileManager defaultManager] createDirectoryAtPath:appSupportDir withIntermediateDirectories:YES attributes:nil error:&error]) {
+ NSLog(@"%@", error.localizedDescription);
+ }
+ else {
+ // *** OPTIONAL *** Mark the directory as excluded from iCloud backups
+ NSURL *url = [NSURL fileURLWithPath:appSupportDir];
+ if (![url setResourceValue:@YES
+ forKey:NSURLIsExcludedFromBackupKey
+ error:&error])
+ {
+ NSLog(@"Error excluding %@ from backup %@", url.lastPathComponent, error.localizedDescription);
+ }
+ else {
+ NSLog(@"Yay");
+ }
+ }
+ }
+ printf("%s\n", [appSupportDir UTF8String]);
+}
diff --git a/soh/macosx/launcher.sh b/soh/macosx/launcher.sh
new file mode 100755
index 000000000..ef22983de
--- /dev/null
+++ b/soh/macosx/launcher.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+APPPATH="${0%/*}"
+cd "${APPPATH}"
+APPPATH=$(pwd)
+APPSUPPORT=$(./appsupport)
+mkdir -p "${APPSUPPORT}/com.shipofharkinian.soh"
+cd "${APPSUPPORT}/com.shipofharkinian.soh"
+cp "${APPPATH}/oot.otr" .
+${APPPATH}/soh
diff --git a/soh/macosx/sohIcon.png b/soh/macosx/sohIcon.png
new file mode 100644
index 000000000..736334dc9
--- /dev/null
+++ b/soh/macosx/sohIcon.png
Binary files differ
diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp
index 44d0facd4..d9e7949c5 100644
--- a/soh/soh/OTRGlobals.cpp
+++ b/soh/soh/OTRGlobals.cpp
@@ -40,7 +40,12 @@
#include "macros.h"
#include <Utils/StringHelper.h>
+#ifdef __APPLE__
+#include <SDL_scancode.h>
+#else
#include <SDL2/SDL_scancode.h>
+#endif
+
#include <Audio.h>
OTRGlobals* OTRGlobals::Instance;
diff --git a/soh/src/buffers/heaps.c b/soh/src/buffers/heaps.c
index b6f16ab11..410c843a5 100644
--- a/soh/src/buffers/heaps.c
+++ b/soh/src/buffers/heaps.c
@@ -1,6 +1,8 @@
#include "z64.h"
#include <assert.h>
+#ifndef __APPLE__
#include <malloc.h>
+#endif
#ifndef _MSC_VER
#include <unistd.h>
diff --git a/soh/src/code/code_800EC960.c b/soh/src/code/code_800EC960.c
index 9a67981ea..8e1694b7c 100644
--- a/soh/src/code/code_800EC960.c
+++ b/soh/src/code/code_800EC960.c
@@ -4527,12 +4527,17 @@ void Audio_PlayFanfare(u16 seqId)
sp26 = func_800FA0B4(SEQ_PLAYER_FANFARE);
sp1C = func_800E5E84(sp26 & 0xFF, &sp20);
sp18 = func_800E5E84(seqId & 0xFF, &sp20);
- if ((sp26 == NA_BGM_DISABLED) || (*sp1C == *sp18)) {
- D_8016B9F4 = 1;
- } else {
- D_8016B9F4 = 5;
- Audio_SeqCmd1(SEQ_PLAYER_FANFARE, 0);
- }
+ if (!sp1C || !sp18) {
+ // disable BGM, we're about to null deref!
+ D_8016B9F4 = 1;
+ } else {
+ if ((sp26 == NA_BGM_DISABLED) || (*sp1C == *sp18)) {
+ D_8016B9F4 = 1;
+ } else {
+ D_8016B9F4 = 5;
+ Audio_SeqCmd1(SEQ_PLAYER_FANFARE, 0);
+ }
+ }
D_8016B9F6 = seqId;
}