mirror of
https://github.com/libretro/Libretro-Supermodel.git
synced 2026-11-10 03:01:26 -10:00
Simulate the Model 3 network board in the Libretro core and carry its frames over RetroArch Netplay's packet interface (RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE), so linked cabinets can play together without the standalone socket board. Supported families: Daytona USA 2, Harley-Davidson, Scud Race, Sega Rally 2, Ski Champ, Spikeout and Spikeout Final Edition (Type 1); Le Mans 24, Virtual On 2 and Dirt Devils (Type 2). Two to sixteen cabinets, with a handshake, a common roster, role checks and a per-frame exchange with a timeout. New options: Network Board (connected by default) and Linked Cabinets (2-16). Squashed from these commits, whose intermediate steps (Daytona 2 only, then Scud Race, then all Type 1, then Type 2) have no value on their own:e7ea7d48b0Add experimental Daytona 2 cabinet networking437256ddbbAdd experimental Scud Race cabinet networkingc4f012958aRecognize linked-cabinet network hardwared43eda03ecEnable Sega Rally 2 network transport55b59bbcb3Support multi-cabinet linked playbc3788aea7Enable netpacket transport for all Type 1 gamesf7029c25f6Add Type 2 linked-cabinet transport03ee7631c0Connect the network board by defaultad99627b37Document all supported linked-cabinet families74da0c469bDocument linked-cabinet role requirements (option text) Adapted on dev: - The game-aware NVRAM settings options are not on dev, so each cabinet's link role (Master/Slave/Satellite) and car or machine number are set in the game's Service Menu, as on real cabinets; the option descriptions say so. Option visibility per game is left out. - The NetBoard config defaults were only defined for Windows; they are now defined on every platform, and NetworkCabinets uses unsigned bounds so it compiles. - Network, NetworkCabinets and SimulateNet are applied after the Supermodel.ini merge, like the other core options. - jni/Android.mk gets -DNET_BOARD and the new source file. - The README part of74da0c4waits for the dev README. Tested: Linux, two RetroArch 1.22.2 instances over localhost Netplay: Daytona 2 (Type 1) and Le Mans 24 (Type 2) link as Master and Slave and exchange frames; Daytona 2 races show the other cabinet's car at full speed. Single player with the board connected and no Netplay: Daytona 2, Scud Race, Sega Rally 2 and Le Mans 24 boot to attract mode as before, same speed and log. Windows, macOS, RPi5 and Android arm64 (ndk-build) builds pass.
763 lines
30 KiB
Makefile
763 lines
30 KiB
Makefile
# Supermodel Libretro Core - Unified Makefile
|
|
# Follows libretro/skeletor pattern with all platforms consolidated
|
|
|
|
STATIC_LINKING := 0
|
|
DEBUG ?= 0
|
|
PSS_STYLE ?= 1
|
|
EXTERNAL_ZLIB ?= 0
|
|
HAVE_GRIFFIN ?= 1
|
|
|
|
# Core definitions
|
|
CORE_DIR := .
|
|
TARGET_NAME := supermodel
|
|
|
|
# ============================================================
|
|
# Platform Auto-Detection
|
|
# ============================================================
|
|
ifeq ($(platform),)
|
|
platform = unix
|
|
ifeq ($(shell uname -a),)
|
|
platform = win
|
|
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
|
platform = win
|
|
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
|
platform = osx
|
|
else ifneq ($(findstring win,$(shell uname -a)),)
|
|
platform = win
|
|
else ifeq ($(shell uname -m),aarch64)
|
|
platform = linux-aarch64
|
|
endif
|
|
endif
|
|
|
|
# The libretro buildbot passes platform=win64 to the MinGW cross build, and
|
|
# other spellings are in circulation too. Normalize them all to "win" so the
|
|
# Windows branches below actually match -- otherwise no branch matches at all,
|
|
# TARGET stays empty and "make" silently does nothing.
|
|
WIN_PLATFORM := $(filter $(platform),win win32 win64 windows wincross64)
|
|
ifneq (,$(WIN_PLATFORM))
|
|
platform := win
|
|
endif
|
|
|
|
# System platform (for native builds)
|
|
system_platform = unix
|
|
ifeq ($(shell uname -a),)
|
|
system_platform = win
|
|
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
|
system_platform = osx
|
|
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
|
system_platform = win
|
|
endif
|
|
|
|
# ============================================================
|
|
# Source Files (extracted from Makefile.common)
|
|
# ============================================================
|
|
LIBRETRO_COMM_DIR := $(CORE_DIR)/Src/OSD/libretro/libretro-common
|
|
DEPS_DIR := $(CORE_DIR)/deps
|
|
|
|
INCFLAGS := -I$(CORE_DIR) \
|
|
-I$(DEPS_DIR)/ugui \
|
|
-I$(LIBRETRO_COMM_DIR)/include \
|
|
-I$(CORE_DIR)/Src/OSD/libretro/include \
|
|
-I$(CORE_DIR)/Src/OSD/libretro \
|
|
-I$(CORE_DIR)/Src \
|
|
-I$(CORE_DIR)/Src/CPU/68K/Musashi \
|
|
-I$(CORE_DIR)/Src/CPU/68K/Musashi/generated
|
|
|
|
COREDEFINES := -D__LIBRETRO__ -DSUPERMODEL_OSD_LIBRETRO -DNET_BOARD
|
|
COREDEFINES += -DINLINE=inline
|
|
COREDEFINES += -DPSS_STYLE=$(PSS_STYLE)
|
|
|
|
# C Source Files (28 files)
|
|
SOURCES_C := $(CORE_DIR)/Src/Pkgs/unzip.c \
|
|
$(CORE_DIR)/Src/Pkgs/ioapi.c \
|
|
$(CORE_DIR)/Src/CPU/68K/Musashi/m68kcpu.c \
|
|
$(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kops.c \
|
|
$(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kopac.c \
|
|
$(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kopdm.c \
|
|
$(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kopnz.c \
|
|
$(DEPS_DIR)/ugui/ugui.c \
|
|
$(CORE_DIR)/Src/ugui_tools.c \
|
|
$(LIBRETRO_COMM_DIR)/streams/file_stream.c \
|
|
$(LIBRETRO_COMM_DIR)/streams/file_stream_transforms.c \
|
|
$(LIBRETRO_COMM_DIR)/file/file_path.c \
|
|
$(LIBRETRO_COMM_DIR)/file/file_path_io.c \
|
|
$(LIBRETRO_COMM_DIR)/file/retro_dirent.c \
|
|
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c \
|
|
$(LIBRETRO_COMM_DIR)/lists/dir_list.c \
|
|
$(LIBRETRO_COMM_DIR)/lists/string_list.c \
|
|
$(LIBRETRO_COMM_DIR)/string/stdstring.c \
|
|
$(LIBRETRO_COMM_DIR)/compat/compat_strl.c \
|
|
$(LIBRETRO_COMM_DIR)/compat/fopen_utf8.c \
|
|
$(LIBRETRO_COMM_DIR)/compat/compat_strcasestr.c \
|
|
$(LIBRETRO_COMM_DIR)/compat/compat_posix_string.c \
|
|
$(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \
|
|
$(LIBRETRO_COMM_DIR)/memmap/memalign.c \
|
|
$(LIBRETRO_COMM_DIR)/time/rtime.c \
|
|
$(LIBRETRO_COMM_DIR)/hash/rhash.c
|
|
|
|
# Add libretro-common glsym for non-Android
|
|
ifeq (,$(findstring android,$(platform)))
|
|
SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_gl.c \
|
|
$(LIBRETRO_COMM_DIR)/glsym/rglgen.c
|
|
endif
|
|
|
|
# C++ Source Files (80 files - verified to exist)
|
|
SOURCES_CXX := $(CORE_DIR)/Src/CPU/PowerPC/PPCDisasm.cpp \
|
|
$(CORE_DIR)/Src/BlockFile.cpp \
|
|
$(CORE_DIR)/Src/Model3/93C46.cpp \
|
|
$(CORE_DIR)/Src/Util/BitRegister.cpp \
|
|
$(CORE_DIR)/Src/Model3/JTAG.cpp \
|
|
$(CORE_DIR)/Src/Pkgs/imgui/imgui.cpp \
|
|
$(CORE_DIR)/Src/Pkgs/imgui/imgui_draw.cpp \
|
|
$(CORE_DIR)/Src/Pkgs/imgui/imgui_tables.cpp \
|
|
$(CORE_DIR)/Src/Pkgs/imgui/imgui_widgets.cpp \
|
|
$(CORE_DIR)/Src/Pkgs/imgui/imgui_impl_opengl3.cpp \
|
|
$(CORE_DIR)/Src/Graphics/Legacy3D/Error.cpp \
|
|
$(CORE_DIR)/Src/Graphics/Shader.cpp \
|
|
$(CORE_DIR)/Src/Graphics/GLSLVersion.cpp \
|
|
$(CORE_DIR)/Src/Model3/Real3D.cpp \
|
|
$(CORE_DIR)/Src/Graphics/Legacy3D/Legacy3D.cpp \
|
|
$(CORE_DIR)/Src/Graphics/Legacy3D/Models.cpp \
|
|
$(CORE_DIR)/Src/Graphics/Legacy3D/TextureRefs.cpp \
|
|
$(CORE_DIR)/Src/Graphics/New3D/New3D.cpp \
|
|
$(CORE_DIR)/Src/Graphics/New3D/Mat4.cpp \
|
|
$(CORE_DIR)/Src/Graphics/New3D/Model.cpp \
|
|
$(CORE_DIR)/Src/Graphics/New3D/PolyHeader.cpp \
|
|
$(CORE_DIR)/Src/Graphics/New3D/TextureBank.cpp \
|
|
$(CORE_DIR)/Src/Graphics/New3D/VBO.cpp \
|
|
$(CORE_DIR)/Src/Graphics/New3D/Vec.cpp \
|
|
$(CORE_DIR)/Src/Graphics/New3D/R3DShader.cpp \
|
|
$(CORE_DIR)/Src/Graphics/New3D/R3DFloat.cpp \
|
|
$(CORE_DIR)/Src/Graphics/New3D/R3DScrollFog.cpp \
|
|
$(CORE_DIR)/Src/Graphics/New3D/R3DFrameBuffers.cpp \
|
|
$(CORE_DIR)/Src/Graphics/New3D/GLSLShader.cpp \
|
|
$(CORE_DIR)/Src/Graphics/FBO.cpp \
|
|
$(CORE_DIR)/Src/Graphics/SuperAA.cpp \
|
|
$(CORE_DIR)/Src/Graphics/Render2D.cpp \
|
|
$(CORE_DIR)/Src/Model3/TileGen.cpp \
|
|
$(CORE_DIR)/Src/Model3/Model3.cpp \
|
|
$(CORE_DIR)/Src/CPU/PowerPC/ppc.cpp \
|
|
$(if $(filter android aarch64 rpi64 linux-aarch64 osx,$(platform)),$(CORE_DIR)/Src/CPU/PowerPC/Jit/JitArm64.cpp,) \
|
|
$(CORE_DIR)/Src/Model3/SoundBoard.cpp \
|
|
$(CORE_DIR)/Src/Sound/SCSP.cpp \
|
|
$(CORE_DIR)/Src/Sound/SCSPDSP.cpp \
|
|
$(CORE_DIR)/Src/CPU/68K/68K.cpp \
|
|
$(CORE_DIR)/Src/Model3/DSB.cpp \
|
|
$(CORE_DIR)/Src/CPU/Z80/Z80.cpp \
|
|
$(CORE_DIR)/Src/Model3/IRQ.cpp \
|
|
$(CORE_DIR)/Src/Model3/53C810.cpp \
|
|
$(CORE_DIR)/Src/Model3/PCI.cpp \
|
|
$(CORE_DIR)/Src/Model3/RTC72421.cpp \
|
|
$(CORE_DIR)/Src/Model3/DriveBoard/DriveBoard.cpp \
|
|
$(CORE_DIR)/Src/Model3/DriveBoard/WheelBoard.cpp \
|
|
$(CORE_DIR)/Src/Model3/DriveBoard/JoystickBoard.cpp \
|
|
$(CORE_DIR)/Src/Model3/DriveBoard/SkiBoard.cpp \
|
|
$(CORE_DIR)/Src/Model3/DriveBoard/BillBoard.cpp \
|
|
$(CORE_DIR)/Src/Model3/DriveBoard/Z80CTC.cpp \
|
|
$(CORE_DIR)/Src/Model3/MPC10x.cpp \
|
|
$(CORE_DIR)/Src/Inputs/Input.cpp \
|
|
$(CORE_DIR)/Src/Inputs/Inputs.cpp \
|
|
$(CORE_DIR)/Src/Inputs/InputSource.cpp \
|
|
$(CORE_DIR)/Src/Inputs/InputSystem.cpp \
|
|
$(CORE_DIR)/Src/Inputs/InputTypes.cpp \
|
|
$(CORE_DIR)/Src/Inputs/MultiInputSource.cpp \
|
|
$(CORE_DIR)/Src/OSD/Outputs.cpp \
|
|
$(CORE_DIR)/Src/Sound/MPEG/MpegAudio.cpp \
|
|
$(CORE_DIR)/Src/Model3/Crypto.cpp \
|
|
$(CORE_DIR)/Src/OSD/Logger.cpp \
|
|
$(CORE_DIR)/Src/Util/Format.cpp \
|
|
$(CORE_DIR)/Src/Util/NewConfig.cpp \
|
|
$(CORE_DIR)/Src/Util/ByteSwap.cpp \
|
|
$(CORE_DIR)/Src/Util/ConfigBuilders.cpp \
|
|
$(CORE_DIR)/Src/GameLoader.cpp \
|
|
$(CORE_DIR)/Src/Pkgs/tinyxml2.cpp \
|
|
$(CORE_DIR)/Src/ROMSet.cpp \
|
|
$(CORE_DIR)/Src/OSD/libretro/libretroAudio.cpp \
|
|
$(CORE_DIR)/Src/OSD/libretro/libretroThread.cpp \
|
|
$(CORE_DIR)/Src/OSD/libretro/libretroCrosshair.cpp \
|
|
$(CORE_DIR)/Src/OSD/libretro/libretroGui.cpp \
|
|
$(CORE_DIR)/Src/OSD/libretro/LibretroBlockFileMemory.cpp \
|
|
$(CORE_DIR)/Src/OSD/libretro/CLibretroInputSystem.cpp \
|
|
$(CORE_DIR)/Src/OSD/libretro/CLibretroOutputSystem.cpp \
|
|
$(CORE_DIR)/Src/OSD/libretro/LibretroNetBoard.cpp \
|
|
$(CORE_DIR)/Src/OSD/libretro/LibretroWrapper.cpp \
|
|
$(CORE_DIR)/Src/OSD/libretro/vfs_ioapi.cpp \
|
|
$(CORE_DIR)/Src/OSD/libretro/libretro.cpp
|
|
|
|
# Platform-specific OSD FileSystemPath implementation
|
|
ifeq ($(platform),win)
|
|
SOURCES_CXX += $(CORE_DIR)/Src/OSD/Windows/FileSystemPath.cpp
|
|
else ifeq ($(platform),osx)
|
|
SOURCES_CXX += $(CORE_DIR)/Src/OSD/OSX/FileSystemPath.cpp
|
|
else
|
|
# osx, unix, android, rpi64, aarch64 all use Unix FileSystemPath
|
|
SOURCES_CXX += $(CORE_DIR)/Src/OSD/Unix/FileSystemPath.cpp
|
|
endif
|
|
|
|
# Renderer selection: new3d (default) or legacy.
|
|
# make platform=rpi64 RENDERER=legacy
|
|
# Legacy3D is the old desktop-GL renderer. It is being ported to run inside the
|
|
# GLES3 context (GLES2-style code: client vertex arrays, #version 100 shaders),
|
|
# so on GLES platforms it is only compiled in when explicitly asked for.
|
|
RENDERER ?= new3d
|
|
|
|
LEGACY3D_SOURCES := %/Legacy3D/Error.cpp %/Legacy3D/Legacy3D.cpp %/Legacy3D/Models.cpp %/Legacy3D/TextureRefs.cpp
|
|
|
|
ifeq ($(RENDERER),legacy)
|
|
RENDERER_DEFINES := -DUSE_LEGACY3D
|
|
DROP_LEGACY3D :=
|
|
else
|
|
RENDERER_DEFINES :=
|
|
DROP_LEGACY3D := 1
|
|
endif
|
|
|
|
# Platform-specific source filtering (MUST be before OBJECTS computation!)
|
|
# macOS and Android don't support Legacy3D (old fixed-pipeline OpenGL)
|
|
ifeq ($(platform),osx)
|
|
SOURCES_CXX := $(filter-out $(LEGACY3D_SOURCES),$(SOURCES_CXX))
|
|
endif
|
|
ifeq ($(platform),android)
|
|
SOURCES_CXX := $(filter-out $(LEGACY3D_SOURCES),$(SOURCES_CXX))
|
|
endif
|
|
|
|
# rpi64 and aarch64 use GLES3 (RetroArch on RPi5 provides only GLES context via EGL)
|
|
ifeq ($(platform),rpi64)
|
|
SOURCES_C := $(filter-out %/glsym/glsym_gl.c,$(SOURCES_C))
|
|
SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_es3.c
|
|
ifdef DROP_LEGACY3D
|
|
SOURCES_CXX := $(filter-out $(LEGACY3D_SOURCES),$(SOURCES_CXX))
|
|
endif
|
|
endif
|
|
ifeq ($(platform),aarch64)
|
|
SOURCES_C := $(filter-out %/glsym/glsym_gl.c,$(SOURCES_C))
|
|
SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_es3.c
|
|
ifdef DROP_LEGACY3D
|
|
SOURCES_CXX := $(filter-out $(LEGACY3D_SOURCES),$(SOURCES_CXX))
|
|
endif
|
|
endif
|
|
ifeq ($(platform),linux-aarch64)
|
|
SOURCES_C := $(filter-out %/glsym/glsym_gl.c,$(SOURCES_C))
|
|
SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_es3.c
|
|
ifdef DROP_LEGACY3D
|
|
SOURCES_CXX := $(filter-out $(LEGACY3D_SOURCES),$(SOURCES_CXX))
|
|
endif
|
|
endif
|
|
# iOS and tvOS are GLES too, and there is no desktop GL on either to fall back
|
|
# on, so Legacy3D goes whatever RENDERER says, as it does for osx and android.
|
|
ifneq ($(filter $(platform),ios-arm64 tvos-arm64),)
|
|
SOURCES_C := $(filter-out %/glsym/glsym_gl.c,$(SOURCES_C))
|
|
SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_es3.c
|
|
SOURCES_CXX := $(filter-out $(LEGACY3D_SOURCES),$(SOURCES_CXX))
|
|
endif
|
|
|
|
# Tell the Libretro option layer whether Legacy3D is in this build, after all the
|
|
# platform filtering above, so the 3D Renderer option only appears where it works.
|
|
ifneq ($(filter %/Legacy3D/Legacy3D.cpp,$(SOURCES_CXX)),)
|
|
RENDERER_DEFINES += -DHAVE_LEGACY3D
|
|
endif
|
|
|
|
# GIT version
|
|
GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)"
|
|
ifneq ($(GIT_VERSION)," unknown")
|
|
COREDEFINES += -DGIT_VERSION=\"$(GIT_VERSION)\"
|
|
endif
|
|
|
|
# Platform-specific defines (to be assembled with COREDEFINES into final DEFINES)
|
|
PLATFORM_DEFINES :=
|
|
|
|
# ============================================================
|
|
# Platform-Specific Configuration
|
|
# ============================================================
|
|
|
|
# ============ UNIX/LINUX (Default) ============
|
|
ifeq ($(platform),unix)
|
|
TARGET := $(TARGET_NAME)_libretro.so
|
|
LDFLAGS += -shared -fPIC
|
|
CFLAGS += -fPIC
|
|
CXXFLAGS += -fPIC
|
|
# Legacy3D uses GLU's perspective helper. Unlike desktop OpenGL entry
|
|
# points supplied by the Libretro frontend, GLU is not guaranteed to be
|
|
# exported by the frontend process and must be an explicit dependency.
|
|
LIBS += -ldl -lm -lz -lGLU
|
|
ifeq ($(strip $(CROSS_COMPILE)),)
|
|
INCFLAGS += -I/usr/include
|
|
endif
|
|
endif
|
|
|
|
# ============ Linux ARM64 (native — CI runner, RPi4/5, ARM64 SBCs) ============
|
|
# Auto-selected when platform is unset and uname -m is aarch64.
|
|
# Uses the native compiler; enables GLES3 + JIT (required for RetroArch on RPi).
|
|
# For cross-compiling from x86 to RPi, use platform=rpi64 instead.
|
|
ifeq ($(platform),linux-aarch64)
|
|
TARGET := $(TARGET_NAME)_libretro.so
|
|
fpic := -fPIC
|
|
SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T -Wl,-no-undefined
|
|
LDFLAGS += $(SHARED)
|
|
CFLAGS += -fPIC
|
|
CXXFLAGS += -fPIC
|
|
LIBS += -ldl -lm -lz
|
|
|
|
PLATFORM_DEFINES += -DARM -D__aarch64__ -DLSB_FIRST -DGL_GLEXT_PROTOTYPES -DHAVE_PPC_JIT
|
|
PLATFORM_DEFINES += -DGLES -Dgles -DHAVE_OPENGLES=1 -DHAVE_OPENGLES3=1 -DCORE_GLES -D__glext_h_ -D__GLEXT_H_
|
|
|
|
CXXFLAGS += -std=c++17
|
|
endif
|
|
|
|
# ============ iOS / tvOS (arm64) ============
|
|
# Both are the GLES build with Apple's SDK in front of it: the renderer resolves
|
|
# every entry point through glsym, so nothing links against a GL framework here
|
|
# any more than it does on the other GLES platforms, and OpenGLES is deprecated
|
|
# on these systems anyway.
|
|
#
|
|
# No PPC JIT. Writing and then executing the same page needs an entitlement that
|
|
# a libretro core cannot ask for on stock iOS or tvOS, so the recompiler is out
|
|
# and Model 3 runs on the interpreter. That is the same bargain every emulator
|
|
# on these systems makes, and it is the reason to be honest about what the
|
|
# artifact is rather than to leave the platform unbuilt.
|
|
#
|
|
# The dylib names are what the libretro ios-arm64 and tvos-arm64 templates look
|
|
# for, and their after_script checks the platform recorded in the Mach-O, which
|
|
# is what -isysroot and the version-min flag put there.
|
|
ifneq ($(filter $(platform),ios-arm64 tvos-arm64),)
|
|
ifeq ($(platform),ios-arm64)
|
|
TARGET := $(TARGET_NAME)_libretro_ios.dylib
|
|
APPLE_SDK := $(shell xcrun -sdk iphoneos -show-sdk-path)
|
|
APPLE_MIN := -miphoneos-version-min=13.0
|
|
PLATFORM_DEFINES += -DIOS
|
|
else
|
|
TARGET := $(TARGET_NAME)_libretro_tvos.dylib
|
|
APPLE_SDK := $(shell xcrun -sdk appletvos -show-sdk-path)
|
|
APPLE_MIN := -mappletvos-version-min=13.0
|
|
PLATFORM_DEFINES += -DTVOS
|
|
endif
|
|
|
|
# Same lesson as the bundled headers above: a tool that is not there should
|
|
# stop the build where it is missing, not hand the compiler an empty
|
|
# -isysroot and let it fail later on a header it cannot find.
|
|
ifeq ($(APPLE_SDK),)
|
|
$(error xcrun found no SDK for $(platform) - is Xcode installed and selected?)
|
|
endif
|
|
|
|
CC := clang
|
|
CXX := clang++
|
|
|
|
ARCHFLAGS := -arch arm64 -isysroot $(APPLE_SDK) $(APPLE_MIN)
|
|
CFLAGS += -fPIC $(ARCHFLAGS)
|
|
CXXFLAGS += -fPIC $(ARCHFLAGS) -std=c++17
|
|
LDFLAGS += -dynamiclib -fPIC $(ARCHFLAGS)
|
|
|
|
# dlopen lives in libc on these systems, so there is no -ldl to link.
|
|
LIBS += -lm -lz
|
|
|
|
PLATFORM_DEFINES += -DARM -D__aarch64__ -DLSB_FIRST -DGL_GLEXT_PROTOTYPES
|
|
PLATFORM_DEFINES += -DGLES -Dgles -DHAVE_OPENGLES=1 -DHAVE_OPENGLES3=1 -DCORE_GLES -D__glext_h_ -D__GLEXT_H_
|
|
PLATFORM_DEFINES += -DGL_SILENCE_DEPRECATION
|
|
endif
|
|
|
|
# ============ macOS / osxcross ============
|
|
ifeq ($(platform),osx)
|
|
TARGET := $(TARGET_NAME)_libretro.dylib
|
|
# __gcov_dump is an optional profiling hook. Keep only that symbol weakly
|
|
# importable so missing core dependencies still fail at link time.
|
|
LDFLAGS += -dynamiclib -fPIC -Wl,-U,___gcov_dump
|
|
CFLAGS += -fPIC
|
|
CXXFLAGS += -fPIC
|
|
LIBS += -lm -framework OpenGL -framework CoreFoundation
|
|
PLATFORM_DEFINES += -DGL_SILENCE_DEPRECATION
|
|
|
|
ifeq ($(system_platform),osx)
|
|
# Native macOS build (CI macOS runner or local Mac developer build).
|
|
# Build for the host arch so the CI x64 job → x86_64, arm64 job → arm64.
|
|
NATIVE_ARCH := $(shell uname -m)
|
|
ARCHFLAGS := -arch $(NATIVE_ARCH) -mmacosx-version-min=10.15
|
|
CFLAGS += $(ARCHFLAGS)
|
|
CXXFLAGS += $(ARCHFLAGS)
|
|
LDFLAGS += $(ARCHFLAGS)
|
|
|
|
# Apple Silicon requires MAP_JIT plus per-thread W^X switching. Keep
|
|
# Intel and universal cross-builds on the interpreter.
|
|
ifeq ($(NATIVE_ARCH),arm64)
|
|
PLATFORM_DEFINES += -DHAVE_PPC_JIT
|
|
endif
|
|
else
|
|
# Cross-compile from Linux via osxcross (universal x86_64 + arm64 dylib).
|
|
OSXCROSS_ROOT ?= /opt/osxcross
|
|
OSXCROSS_PATH := $(OSXCROSS_ROOT)/target/bin
|
|
|
|
ifeq ($(wildcard $(OSXCROSS_PATH)/o64-clang++),)
|
|
$(error osxcross not found at $(OSXCROSS_ROOT). Install: cd /tmp && git clone https://github.com/tpoechtrager/osxcross.git && cd osxcross && wget -nc https://github.com/rtrussell/osxcross-build/releases/download/12.0/MacOSX12.0.sdk.tar.xz -O tarballs/MacOSX12.0.sdk.tar.xz && ./build.sh)
|
|
endif
|
|
|
|
export PATH := $(OSXCROSS_PATH):$(PATH)
|
|
export LD_LIBRARY_PATH := $(OSXCROSS_ROOT)/target/lib:$(LD_LIBRARY_PATH)
|
|
override CC := o64-clang
|
|
override CXX := o64-clang++
|
|
override LD := o64-clang++
|
|
|
|
ARCHFLAGS := -arch x86_64 -arch arm64
|
|
CFLAGS += $(ARCHFLAGS)
|
|
CXXFLAGS += $(ARCHFLAGS)
|
|
LDFLAGS += $(ARCHFLAGS)
|
|
|
|
MACOSX_SDK ?= /opt/osxcross/target/SDK/MacOSX12.0.sdk
|
|
CFLAGS += -isysroot $(MACOSX_SDK)
|
|
CXXFLAGS += -isysroot $(MACOSX_SDK)
|
|
LDFLAGS += -isysroot $(MACOSX_SDK)
|
|
|
|
LDFLAGS += -static-libstdc++
|
|
endif
|
|
endif
|
|
|
|
# ============ ANDROID ============
|
|
ifeq ($(platform),android)
|
|
TARGET := $(TARGET_NAME)_libretro_android.so
|
|
fpic := -fPIC
|
|
SHARED := -shared
|
|
PLATFORM_DEFINES += -DANDROID -D__LIBRETRO__ -DPSS_STYLE=1 -D_FILE_OFFSET_BITS=64
|
|
PLATFORM_DEFINES += -D_POSIX_C_SOURCE=200809L -D_GNU_SOURCE
|
|
PLATFORM_DEFINES += -DEGL_EGLEXT_PROTOTYPES
|
|
LIBS += -lGLESv3 -llog -lz
|
|
|
|
# Prepend Android shim headers to resolve <GL/glew.h> to our shim
|
|
INCFLAGS := -I$(CORE_DIR)/Src/OSD/Android/include $(INCFLAGS)
|
|
|
|
# --- NDK Detection ---
|
|
# Check common locations if NDK_ROOT is not already set
|
|
ifeq ($(NDK_ROOT),)
|
|
NDK_ROOT := $(shell ls -d ~/Android/Sdk/ndk/28.2.13676358 2>/dev/null)
|
|
endif
|
|
|
|
# Performance Flags from Mupen64Plus
|
|
HAVE_NEON := 0
|
|
ifeq ($(arch),arm)
|
|
HAVE_NEON := 1
|
|
endif
|
|
ifeq ($(arch),arm64)
|
|
HAVE_NEON := 1
|
|
endif
|
|
|
|
# LTO Control - Disable for Android due to PIC relocation issues with NDK clang
|
|
HAVE_LTCG := 0
|
|
|
|
# If NDK is found, use its Clang toolchain
|
|
ifneq ($(NDK_ROOT),)
|
|
# Default to aarch64 (64-bit ARM) if no 'arch' is specified
|
|
ifeq ($(arch),arm)
|
|
ARCH_TRIPLE := arm-linux-androideabi
|
|
CLANG_TRIPLE := armv7a-linux-androideabi24
|
|
PLATFORM_DEFINES += -march=armv7-a -mfloat-abi=softfp -mfpu=neon
|
|
else ifeq ($(arch),x86)
|
|
ARCH_TRIPLE := i686-linux-android
|
|
CLANG_TRIPLE := i686-linux-android24
|
|
else ifeq ($(arch),x86_64)
|
|
ARCH_TRIPLE := x86_64-linux-android
|
|
CLANG_TRIPLE := x86_64-linux-android24
|
|
else
|
|
# Default to arm64 (aarch64)
|
|
ARCH_TRIPLE := aarch64-linux-android
|
|
CLANG_TRIPLE := aarch64-linux-android24
|
|
PLATFORM_DEFINES += -DHAVE_PPC_JIT
|
|
endif
|
|
|
|
TOOLCHAIN := $(NDK_ROOT)/toolchains/llvm/prebuilt/linux-x86_64/bin
|
|
CC := $(TOOLCHAIN)/$(CLANG_TRIPLE)-clang
|
|
CXX := $(TOOLCHAIN)/$(CLANG_TRIPLE)-clang++
|
|
LD := $(CXX)
|
|
|
|
# Android Clang usually needs some extra flags
|
|
CFLAGS += -ffunction-sections -fdata-sections
|
|
CXXFLAGS += -ffunction-sections -fdata-sections
|
|
LDFLAGS += $(SHARED) -Wl,-soname,$(TARGET) -Wl,--no-undefined
|
|
|
|
# Link C++ library statically to avoid dlopen issues on device
|
|
LDFLAGS += -static-libstdc++
|
|
else
|
|
# Fallback to generic names if NDK not found
|
|
CC = arm-linux-androideabi-gcc
|
|
CXX = arm-linux-androideabi-g++
|
|
LD := $(CXX)
|
|
endif
|
|
|
|
ifeq ($(HAVE_NEON),1)
|
|
PLATFORM_DEFINES += -DHAVE_NEON -D__ARM_NEON__ -ftree-vectorize
|
|
endif
|
|
|
|
OBJOUT = -o
|
|
LINKOUT = -o
|
|
LIBM := -lm
|
|
WARNING_DEFINES := -Wno-write-strings
|
|
|
|
# Ensure CXXFLAGS is appended
|
|
CXXFLAGS += -std=c++17
|
|
|
|
ifeq ($(DEBUG),1)
|
|
CFLAGS += -O0 -g -DDEBUG
|
|
CXXFLAGS += -O0 -g -DDEBUG
|
|
else
|
|
CFLAGS += -O3 -DNDEBUG
|
|
CXXFLAGS += -O3 -DNDEBUG
|
|
|
|
# General Performance Optimizations
|
|
CFLAGS += -ffast-math -funsafe-math-optimizations -fomit-frame-pointer
|
|
CXXFLAGS += -ffast-math -funsafe-math-optimizations -fomit-frame-pointer
|
|
|
|
# Visibility Optimizations
|
|
CFLAGS += -fvisibility=hidden
|
|
CXXFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden
|
|
|
|
# LTO (Link Time Optimization)
|
|
ifeq ($(HAVE_LTCG),1)
|
|
CFLAGS += -flto
|
|
CXXFLAGS += -flto
|
|
LDFLAGS += -flto
|
|
endif
|
|
endif
|
|
endif
|
|
|
|
# ============ WINDOWS / MinGW ============
|
|
ifeq ($(platform),win)
|
|
TARGET := $(TARGET_NAME)_libretro.dll
|
|
LDFLAGS += -shared
|
|
CFLAGS += -D_WIN32 -DWIN32
|
|
CXXFLAGS += -D_WIN32 -DWIN32
|
|
|
|
ifeq ($(system_platform),win)
|
|
# Native Windows build with MinGW
|
|
ifeq ($(origin CC),default)
|
|
CC := gcc
|
|
endif
|
|
ifeq ($(origin CXX),default)
|
|
CXX := g++
|
|
endif
|
|
else
|
|
# Cross-compile to Windows (from Linux). Only fall back to the plain
|
|
# mingw-w64 names when no toolchain was handed to us -- the buildbot's
|
|
# MXE container exports its own (x86_64-w64-mingw32.static-gcc), and
|
|
# overriding that would point us at compilers that do not exist there.
|
|
ifeq ($(WIN_PLATFORM),win32)
|
|
MINGW_PREFIX ?= i686-w64-mingw32
|
|
else
|
|
MINGW_PREFIX ?= x86_64-w64-mingw32
|
|
endif
|
|
ifeq ($(origin CC),default)
|
|
CC := $(MINGW_PREFIX)-gcc
|
|
endif
|
|
ifeq ($(origin CXX),default)
|
|
CXX := $(MINGW_PREFIX)-g++
|
|
endif
|
|
ifeq ($(origin AR),default)
|
|
AR := $(MINGW_PREFIX)-ar
|
|
endif
|
|
endif
|
|
|
|
# Static-link MinGW runtimes and zlib so the DLL is self-contained — no
|
|
# libgcc_s_seh-1.dll / libstdc++-6.dll / zlib1.dll required on the user's system.
|
|
LDFLAGS += -static-libgcc -static-libstdc++
|
|
LIBS += -lm -Wl,-Bstatic -lz -Wl,-Bdynamic -lopengl32 -lglu32 -lgdi32
|
|
endif
|
|
|
|
# ============ Raspberry Pi 64-bit ============
|
|
ifeq ($(platform),rpi64)
|
|
CC = aarch64-linux-gnu-gcc
|
|
CXX = aarch64-linux-gnu-g++
|
|
LD = aarch64-linux-gnu-g++
|
|
|
|
TARGET := $(TARGET_NAME)_libretro_aarch64.so
|
|
fpic := -fPIC
|
|
SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T -Wl,-no-undefined
|
|
|
|
# 1. ARCHITECTURE & FEATURE FLAGS
|
|
PLATFORM_DEFINES += -DARM -D__aarch64__ -DLSB_FIRST -DGL_GLEXT_PROTOTYPES -DHAVE_PPC_JIT
|
|
PLATFORM_DEFINES += -fomit-frame-pointer -ffast-math -funsafe-math-optimizations
|
|
# Prevent system header redeclaration
|
|
PLATFORM_DEFINES += -DGLES -Dgles -DHAVE_OPENGLES=1 -DHAVE_OPENGLES3=1 -DCORE_GLES -D__glext_h_ -D__GLEXT_H_
|
|
|
|
# 2. CPU TUNING
|
|
# platform=rpi64 always matches above, so the specific board must be
|
|
# selected via board=rpi5 / board=rpi4 (e.g. make platform=rpi64 board=rpi5)
|
|
ifeq ($(board), rpi5)
|
|
PLATFORM_DEFINES += -mcpu=cortex-a76
|
|
else ifeq ($(board), rpi4)
|
|
PLATFORM_DEFINES += -mcpu=cortex-a72
|
|
else
|
|
PLATFORM_DEFINES += -mcpu=cortex-a53
|
|
endif
|
|
|
|
# 3. LIBRARY & PATHS
|
|
LDFLAGS += $(SHARED) -L/usr/lib/aarch64-linux-gnu
|
|
LIBS := -lGLESv2 -lz -lm
|
|
|
|
# 4. CXXFLAGS
|
|
CXXFLAGS += -std=c++17
|
|
endif
|
|
|
|
# ============ aarch64 (Generic ARM64) ============
|
|
ifeq ($(platform),aarch64)
|
|
CC = aarch64-linux-gnu-gcc
|
|
CXX = aarch64-linux-gnu-g++
|
|
LD = aarch64-linux-gnu-g++
|
|
|
|
TARGET := $(TARGET_NAME)_libretro.so
|
|
fpic := -fPIC
|
|
SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T -Wl,-no-undefined
|
|
|
|
# 1. ARCHITECTURE & FEATURE FLAGS
|
|
PLATFORM_DEFINES += -DARM -D__aarch64__ -DLSB_FIRST -DGL_GLEXT_PROTOTYPES -DHAVE_PPC_JIT
|
|
PLATFORM_DEFINES += -fomit-frame-pointer -ffast-math -funsafe-math-optimizations
|
|
# Prevent system header redeclaration
|
|
PLATFORM_DEFINES += -DGLES -Dgles -DHAVE_OPENGLES=1 -DHAVE_OPENGLES3=1 -DCORE_GLES -D__glext_h_ -D__GLEXT_H_
|
|
|
|
# 2. LIBRARY & PATHS
|
|
LDFLAGS += $(SHARED) -L/usr/lib/aarch64-linux-gnu
|
|
LIBS := -lGLESv2 -lz -lm
|
|
|
|
# 3. CXXFLAGS
|
|
CXXFLAGS += -std=c++17
|
|
endif
|
|
|
|
# ============ webOS ============
|
|
ifneq (,$(or $(findstring webos,$(CROSS_COMPILE)),$(findstring starfish,$(CROSS_COMPILE))))
|
|
SOURCES_C := $(filter-out %/glsym/glsym_gl.c,$(SOURCES_C))
|
|
SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_es3.c
|
|
|
|
# 1. ARCHITECTURE & FEATURE FLAGS
|
|
ifneq (,$(findstring aarch64,$(CROSS_COMPILE)))
|
|
PLATFORM_DEFINES += -DARM -D__aarch64__ -DLSB_FIRST -DGL_GLEXT_PROTOTYPES -DHAVE_PPC_JIT
|
|
endif
|
|
PLATFORM_DEFINES += -fomit-frame-pointer -ffast-math -funsafe-math-optimizations
|
|
|
|
# Prevent system header redeclaration
|
|
PLATFORM_DEFINES += -DGLES -Dgles -DHAVE_OPENGLES=1 -DHAVE_OPENGLES3=1 -DCORE_GLES -D__glext_h_ -D__GLEXT_H_
|
|
|
|
# 2. LIBRARY & PATHS
|
|
LIBS := -lGLESv2 -lz -lm
|
|
endif
|
|
|
|
OBJECTS := $(SOURCES_C:.c=.o) $(SOURCES_CXX:.cpp=.o)
|
|
DEPFILES := $(OBJECTS:.o=.d)
|
|
|
|
# ============ COMMON COMPILER FLAGS ============
|
|
|
|
# C compiler defaults
|
|
CC ?= gcc
|
|
CXX ?= g++
|
|
AR ?= ar
|
|
|
|
# Assemble final DEFINES from COREDEFINES and PLATFORM_DEFINES (mirrors old build system)
|
|
DEFINES := $(COREDEFINES) $(PLATFORM_DEFINES) $(RENDERER_DEFINES)
|
|
OBJOUT ?= -o
|
|
LINKOUT ?= -o
|
|
LIBM ?= -lm
|
|
WARNING_DEFINES ?= -Wno-write-strings
|
|
|
|
# Base optimization and warning flags
|
|
CFLAGS := $(CFLAGS) -Wall -Wextra -O3 -ffast-math -DHAVE_ZLIB $(fpic)
|
|
CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -std=c++17 -O3 -ffast-math -DHAVE_ZLIB $(fpic)
|
|
|
|
# Include path flags and final defines assembly
|
|
CFLAGS += $(INCFLAGS) $(DEFINES)
|
|
CXXFLAGS += $(INCFLAGS) $(DEFINES)
|
|
|
|
# Debug settings
|
|
ifeq ($(DEBUG),1)
|
|
CFLAGS := $(filter-out -O3,$(CFLAGS)) -g -O0 -DDEBUG
|
|
CXXFLAGS := $(filter-out -O3,$(CXXFLAGS)) -g -O0 -DDEBUG
|
|
LDFLAGS += -g
|
|
endif
|
|
|
|
# External zlib
|
|
ifeq ($(EXTERNAL_ZLIB),1)
|
|
INCFLAGS += $(shell pkg-config --cflags zlib)
|
|
LIBS += $(shell pkg-config --libs zlib)
|
|
else
|
|
LIBS += -lz
|
|
endif
|
|
|
|
# ============================================================
|
|
# Build Rules
|
|
# ============================================================
|
|
|
|
.DEFAULT_GOAL := all
|
|
|
|
BUNDLED_GAMES_XML_H := $(CORE_DIR)/Src/OSD/libretro/BundledGamesXml.h
|
|
BUNDLED_SUPERMODEL_H := $(CORE_DIR)/Src/OSD/libretro/BundledSupermodelIni.h
|
|
|
|
$(CORE_DIR)/Src/OSD/libretro/LibretroWrapper.o: \
|
|
$(BUNDLED_GAMES_XML_H) \
|
|
$(BUNDLED_SUPERMODEL_H)
|
|
|
|
.PHONY: all clean info
|
|
$(info PLATFORM_DEFINES ARE: $(PLATFORM_DEFINES))
|
|
all: $(BUNDLED_GAMES_XML_H) $(BUNDLED_SUPERMODEL_H) $(TARGET)
|
|
|
|
$(BUNDLED_GAMES_XML_H): $(CORE_DIR)/Config/Games.xml
|
|
xxd -i $< | sed 's/unsigned char.*\[\]/const unsigned char bundled_games_xml[]/' \
|
|
| sed 's/unsigned int.*_len/const unsigned int bundled_games_xml_len/' > $@
|
|
|
|
$(BUNDLED_SUPERMODEL_H): $(CORE_DIR)/Config/Supermodel.ini
|
|
xxd -i $< | sed 's/unsigned char.*\[\]/const unsigned char bundled_supermodel_ini[]/' \
|
|
| sed 's/unsigned int.*_len/const unsigned int bundled_supermodel_ini_len/' > $@
|
|
|
|
-include $(DEPFILES)
|
|
|
|
$(TARGET): $(OBJECTS)
|
|
@echo "Linking $(TARGET)..."
|
|
$(CXX) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $@
|
|
@echo "Build complete: $@"
|
|
|
|
# Special handling for ppc.o: strip -ffast-math to avoid FENV_ACCESS pragma conflicts
|
|
# ppc_ops.c contains #pragma STDC FENV_ACCESS ON which requires precise FP semantics
|
|
# For Android DEBUG builds, also ensure -fPIC is applied to prevent relocation errors
|
|
$(CORE_DIR)/Src/CPU/PowerPC/ppc.o: CXXFLAGS := $(filter-out -ffast-math -funsafe-math-optimizations,$(CXXFLAGS))
|
|
$(CORE_DIR)/Src/CPU/PowerPC/ppc.o: CXXFLAGS += -Wno-unused-parameter
|
|
|
|
# Both 3D renderers explicitly sanitize NaN/Inf fog values used by Star Wars
|
|
# Trilogy. -ffinite-math-only (part of -ffast-math) removes those checks, so
|
|
# keep the rest of fast-math but allow non-finite values in these files.
|
|
IEEE_FP_RENDERER_OBJECTS := $(CORE_DIR)/Src/Graphics/New3D/New3D.o \
|
|
$(CORE_DIR)/Src/Graphics/Legacy3D/Legacy3D.o
|
|
$(IEEE_FP_RENDERER_OBJECTS): CXXFLAGS += -fno-finite-math-only
|
|
ifeq ($(platform),android)
|
|
ifeq ($(DEBUG),1)
|
|
$(CORE_DIR)/Src/CPU/PowerPC/ppc.o: CXXFLAGS += -fPIC
|
|
endif
|
|
endif
|
|
|
|
# These vendored/generated sources intentionally expose platform-dependent
|
|
# parameters and legacy implementation details that are unused by this core.
|
|
# Keep their known warning noise local instead of weakening warnings globally.
|
|
MUSASHI_OBJECTS := $(CORE_DIR)/Src/CPU/68K/Musashi/m68kcpu.o \
|
|
$(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kops.o \
|
|
$(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kopac.o \
|
|
$(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kopdm.o \
|
|
$(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kopnz.o
|
|
LIBRETRO_COMMON_WARNING_OBJECTS := $(LIBRETRO_COMM_DIR)/file/file_path.o \
|
|
$(LIBRETRO_COMM_DIR)/file/retro_dirent.o \
|
|
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.o \
|
|
$(LIBRETRO_COMM_DIR)/string/stdstring.o
|
|
|
|
$(MUSASHI_OBJECTS): CFLAGS += -Wno-unused-parameter
|
|
$(DEPS_DIR)/ugui/ugui.o: CFLAGS += -Wno-sign-compare -Wno-bitwise-op-parentheses -Wno-unused-but-set-variable
|
|
$(LIBRETRO_COMMON_WARNING_OBJECTS): CFLAGS += -Wno-unused-parameter -Wno-sign-compare
|
|
|
|
%.o: %.c
|
|
$(CC) $(CFLAGS) -MMD -MP -c -o $@ $<
|
|
|
|
%.o: %.cpp
|
|
$(CXX) $(CXXFLAGS) -MMD -MP -c -o $@ $<
|
|
|
|
clean:
|
|
@echo "Cleaning..."
|
|
@rm -f $(OBJECTS) $(DEPFILES) $(TARGET)
|
|
@echo "Clean complete"
|
|
|
|
info:
|
|
@echo "Platform: $(platform)"
|
|
@echo "Target: $(TARGET)"
|
|
@echo "CC: $(CC)"
|
|
@echo "CXX: $(CXX)"
|
|
@echo "CFLAGS: $(CFLAGS)"
|
|
@echo "CXXFLAGS: $(CXXFLAGS)"
|
|
@echo "LDFLAGS: $(LDFLAGS)"
|
|
@echo "LIBS: $(LIBS)"
|