diff options
-rw-r--r-- | backends/module.mk | 5 | ||||
-rw-r--r-- | backends/platform/3ds/3ds.mk | 6 | ||||
-rw-r--r-- | backends/platform/3ds/README.md | 17 | ||||
-rw-r--r-- | backends/platform/3ds/main.cpp | 11 | ||||
-rw-r--r-- | backends/plugins/3ds/3ds-provider.cpp | 127 | ||||
-rw-r--r-- | backends/plugins/3ds/3ds-provider.h | 37 | ||||
-rw-r--r-- | backends/plugins/3ds/plugin.ld | 179 | ||||
-rw-r--r-- | backends/plugins/elf/arm-loader.cpp | 34 | ||||
-rw-r--r-- | backends/plugins/elf/elf-loader.cpp | 32 | ||||
-rw-r--r-- | backends/plugins/elf/elf-loader.h | 4 | ||||
-rw-r--r-- | backends/plugins/elf/mips-loader.cpp | 2 | ||||
-rw-r--r-- | backends/plugins/posix/posix-provider.cpp | 2 | ||||
-rwxr-xr-x | configure | 10 |
13 files changed, 430 insertions, 36 deletions
diff --git a/backends/module.mk b/backends/module.mk index 9424e0abcd..88acd4cfd5 100644 --- a/backends/module.mk +++ b/backends/module.mk @@ -260,6 +260,11 @@ MODULE_OBJS += \ timer/tizen/timer.o endif +ifeq ($(BACKEND),3ds) +MODULE_OBJS += \ + plugins/3ds/3ds-provider.o +endif + ifeq ($(BACKEND),ds) MODULE_OBJS += \ fs/ds/ds-fs.o \ diff --git a/backends/platform/3ds/3ds.mk b/backends/platform/3ds/3ds.mk index 136e9844d9..0954737834 100644 --- a/backends/platform/3ds/3ds.mk +++ b/backends/platform/3ds/3ds.mk @@ -28,7 +28,7 @@ clean_3ds: $(RM) -rf romfs $(RM) -rf dist_3ds -romfs: $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD) $(DIST_3DS_EXTRA_FILES) +romfs: $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD) $(DIST_3DS_EXTRA_FILES) $(PLUGINS) @rm -rf romfs @mkdir -p romfs @cp $(DIST_FILES_THEMES) romfs/ @@ -44,6 +44,10 @@ endif ifdef DIST_3DS_EXTRA_FILES @cp -a $(DIST_3DS_EXTRA_FILES) romfs/ endif +ifeq ($(DYNAMIC_MODULES),1) + @mkdir -p romfs/plugins + @for i in $(PLUGINS); do $(STRIP) --strip-debug $$i -o romfs/plugins/`basename $$i`; done +endif $(TARGET).smdh: $(APP_ICON) @smdhtool --create "$(APP_TITLE)" "$(APP_DESCRIPTION)" "$(APP_AUTHOR)" $(APP_ICON) $@ diff --git a/backends/platform/3ds/README.md b/backends/platform/3ds/README.md index c56669952f..fb30b9fde3 100644 --- a/backends/platform/3ds/README.md +++ b/backends/platform/3ds/README.md @@ -20,7 +20,6 @@ Table of Contents: * * [4.1.1 Compiling third-party libraries](#411-compiling-third-party-libraries) * * [4.1.2 Manually setting up the environment](#412-manually-setting-up-the-environment) * [4.2 Compiling ScummVM](#42-compiling-scummvm) - * [4.3 Warning for build sizes](#43-warning-for-build-sizes) 1.0) Installation ----------------- @@ -222,7 +221,7 @@ The name of the file must be `cacert.pem`. From the root of the scummvm repository: ``` - $ ./configure --host=3ds + $ ./configure --host=3ds --enable-plugins --default-dynamic $ make ``` Additionally compile to specific formats to be used on the 3DS: @@ -230,7 +229,6 @@ Additionally compile to specific formats to be used on the 3DS: $ make scummvm.3dsx $ make scummvm.cia ``` -**_Read the warning about build sizes below._** Assuming everything was successful, you'll be able to find the binary files in the root of your scummvm folder. @@ -238,14 +236,5 @@ files in the root of your scummvm folder. Note: for the CIA format, you will need the 'makerom' and 'bannertool' tools which are not supplied with devkitPro. -4.3) Warning for build sizes ---------------------------- -The above configuration command will include all game engines by default and will -likely be too massive to be stable using either the 3DSX or the CIA format. -Until dynamic modules are figured out, you should configure engines like this: -``` - $ ./configure --host=3ds --disable-all-engines --enable-engine=scumm-7-8,myst,riven, \ - sword1,sword2,sword25,sci,lure,sky,agi,agos -``` -Choose whatever engines you want, but if the ELF's .text section exceeds ~10MB-12MB, -you may experience crashes in memory-intensive games such as COMI, Broken Sword and Discworld 2. +Note: using dynamic plugins as suggested is required when building with most or all of the +game engines enabled in order to keep the memory usage low and avoid stability issues. diff --git a/backends/platform/3ds/main.cpp b/backends/platform/3ds/main.cpp index 18df14b93d..6e33253c08 100644 --- a/backends/platform/3ds/main.cpp +++ b/backends/platform/3ds/main.cpp @@ -21,6 +21,8 @@ */ #include "osystem.h" +#include "backends/plugins/3ds/3ds-provider.h" + #include <3ds.h> #include <malloc.h> @@ -41,12 +43,9 @@ int main(int argc, char *argv[]) { g_system = new _3DS::OSystem_3DS(); assert(g_system); - // Invoke the actual ScummVM main entry point -// if (argc > 2) -// res = scummvm_main(argc-2, &argv[2]); -// else -// res = scummvm_main(argc, argv); -// scummvm_main(0, nullptr); +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new CTRPluginProvider()); +#endif int res = scummvm_main(argc, argv); diff --git a/backends/plugins/3ds/3ds-provider.cpp b/backends/plugins/3ds/3ds-provider.cpp new file mode 100644 index 0000000000..fd813669a5 --- /dev/null +++ b/backends/plugins/3ds/3ds-provider.cpp @@ -0,0 +1,127 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#define FORBIDDEN_SYMBOL_ALLOW_ALL +#include "common/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(__3DS__) + +#include "backends/plugins/3ds/3ds-provider.h" +#include "backends/plugins/elf/arm-loader.h" + +#include "common/debug.h" + +#include <3ds.h> + +extern uint32 __end__; // End of the main program in memory. Set by the linker. + +static uint32 alignUp(uint32 ptr, uint32 align) { + return (ptr + align - 1) & ~(align - 1); +} + +class CTRDLObject : public ARMDLObject { +public: + CTRDLObject(): + ARMDLObject(), + _segmentHeapAddress(0) { + } + +protected: + static const uint32 kPageSize = 0x1000; + + uint32 _segmentHeapAddress; + + void flushDataCache(void *ptr, uint32 len) const override { + svcFlushProcessDataCache(CUR_PROCESS_HANDLE, ptr, len); + } + + void protectMemory(void *ptr, uint32 len, int prot) const override { + debug(2, "elfloader: Protecting memory at %p, len %d with %d", ptr, len, prot); + + uint32 ctrFlags = 0; + if (prot & PF_R) ctrFlags |= MEMPERM_READ; + if (prot & PF_W) ctrFlags |= MEMPERM_WRITE; + if (prot & PF_X) ctrFlags |= MEMPERM_EXECUTE; + + // The kernel expects the range to be aligned to page boundaries + len = alignUp(len, kPageSize); + + Handle currentHandle; + svcDuplicateHandle(¤tHandle, CUR_PROCESS_HANDLE); + svcControlProcessMemory(currentHandle, (uint32)ptr, 0, len, MEMOP_PROT, ctrFlags); + svcCloseHandle(currentHandle); + } + + void *allocateMemory(uint32 align, uint32 size) override { + assert(!_segmentHeapAddress); // At the moment we can only load a single segment + + _segmentHeapAddress = (uint32)ARMDLObject::allocateMemory(align, size); + if (!_segmentHeapAddress) { + return nullptr; + } + + size = alignUp(size, kPageSize); + + // The plugin needs to be loaded near the main executable for PC-relative calls + // to resolve. The segment is allocated on the heap which not in the +/-32 MB + // range of the main executable. So here we map the segment address in the heap + // to a virtual address just after the main executable. + uint32 segmentNearAddress = alignUp((uint32)&__end__, kPageSize) + kPageSize; + + Handle currentHandle; + svcDuplicateHandle(¤tHandle, CUR_PROCESS_HANDLE); + Result mapResult = svcControlProcessMemory(currentHandle, segmentNearAddress, _segmentHeapAddress, size, MEMOP_MAP, MemPerm(MEMPERM_READ | MEMPERM_WRITE)); + svcCloseHandle(currentHandle); + + if (mapResult != 0) { + warning("elfloader: unable to map segment memory (%x) near the excutable (%x)", _segmentHeapAddress, segmentNearAddress); + + ARMDLObject::deallocateMemory((void *)_segmentHeapAddress, size); + _segmentHeapAddress = 0; + return nullptr; + } + + return (void *)segmentNearAddress; + } + + void deallocateMemory(void *ptr, uint32 size) override { + assert(_segmentHeapAddress); + + uint32 alignedSize = alignUp(size, kPageSize); + + Handle currentHandle; + svcDuplicateHandle(¤tHandle, CUR_PROCESS_HANDLE); + svcControlProcessMemory(currentHandle, (uint32)ptr, _segmentHeapAddress, alignedSize, MEMOP_UNMAP, MemPerm(MEMPERM_READ | MEMPERM_WRITE)); + svcCloseHandle(currentHandle); + + ARMDLObject::deallocateMemory((void *)_segmentHeapAddress, size); + + _segmentHeapAddress = 0; + } + +}; + +Plugin *CTRPluginProvider::createPlugin(const Common::FSNode &node) const { + return new TemplatedELFPlugin<CTRDLObject>(node.getPath()); +} + +#endif // defined(DYNAMIC_MODULES) && defined(__3DS__) diff --git a/backends/plugins/3ds/3ds-provider.h b/backends/plugins/3ds/3ds-provider.h new file mode 100644 index 0000000000..c0125e8aec --- /dev/null +++ b/backends/plugins/3ds/3ds-provider.h @@ -0,0 +1,37 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#if defined(DYNAMIC_MODULES) && defined(__3DS__) + +#ifndef BACKENDS_PLUGINS_3DS_PROVIDER_H +#define BACKENDS_PLUGINS_3DS_PROVIDER_H + +#include "backends/plugins/elf/elf-provider.h" + +class CTRPluginProvider : public ELFPluginProvider { +public: + Plugin *createPlugin(const Common::FSNode &node) const; +}; + +#endif // BACKENDS_PLUGINS_3DS_PROVIDER_H + +#endif // defined(DYNAMIC_MODULES) && defined(__3DS__) diff --git a/backends/plugins/3ds/plugin.ld b/backends/plugins/3ds/plugin.ld new file mode 100644 index 0000000000..ae83a7ac2e --- /dev/null +++ b/backends/plugins/3ds/plugin.ld @@ -0,0 +1,179 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +PHDRS +{ + /* ScummVM's elf loader only allows a single segment, at the moment. */ + plugin PT_LOAD FLAGS(7) /* Read | Write | Execute */; +} + +SECTIONS +{ + /* =========== CODE section =========== */ + + . = 0; + + .text ALIGN(0x1000) : + { + /* .text */ + *(.text) + *(.text.*) + *(.glue_7) + *(.glue_7t) + *(.stub) + *(.gnu.warning) + *(.gnu.linkonce.t*) + . = ALIGN(4); + } : plugin + + /* =========== RODATA section =========== */ + + . = ALIGN(0x1000); + + .rodata : + { + *(.rodata) + *(.roda) + *(.rodata.*) + *all.rodata*(*) + *(.gnu.linkonce.r*) + SORT(CONSTRUCTORS) + . = ALIGN(4); + } : plugin + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } : plugin + __exidx_start = .; + ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } : plugin + __exidx_end = .; + + /* =========== DATA section =========== */ + + . = ALIGN(0x1000); + + .data : + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + CONSTRUCTORS + . = ALIGN(4); + } : plugin + + .tdata ALIGN(4) : + { + __tdata_lma = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + . = ALIGN(4); + __tdata_lma_end = .; + } : plugin + + .tbss ALIGN(4) : + { + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + *(.tcommon) + . = ALIGN(4); + } : plugin + + .preinit_array ALIGN(4) : + { + PROVIDE (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + } : plugin + + .init_array ALIGN(4) : + { + PROVIDE (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + } : plugin + + .fini_array ALIGN(4) : + { + PROVIDE (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE (__fini_array_end = .); + } : plugin + + .ctors ALIGN(4) : + { + ___plugin_ctors = .; + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + ___plugin_ctors_end = .; + } : plugin + + .dtors ALIGN(4) : + { + ___plugin_dtors = .; + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + ___plugin_dtors_end = .; + } : plugin + + __bss_start__ = .; + .bss ALIGN(4) : + { + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + *(COMMON) + . = ALIGN(4); + + /* Reserve space for the TLS segment of the main thread */ + __tls_start = .; + . += + SIZEOF(.tdata) + SIZEOF(.tbss); + __tls_end = .; + } : plugin + __bss_end__ = .; + + __end__ = ABSOLUTE(.) ; + + /* ================== + ==== Metadata ==== + ================== */ + + /* Discard sections that difficult post-processing */ + /DISCARD/ : { *(.group .comment .note) } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } +} diff --git a/backends/plugins/elf/arm-loader.cpp b/backends/plugins/elf/arm-loader.cpp index 3aabf44452..3bbb5b2ee5 100644 --- a/backends/plugins/elf/arm-loader.cpp +++ b/backends/plugins/elf/arm-loader.cpp @@ -65,6 +65,7 @@ bool ARMDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment) // Act differently based on the type of relocation switch (REL_TYPE(rel[i].r_info)) { case R_ARM_ABS32: + case R_ARM_TARGET1: if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section. a = *target; // Get full 32 bits of addend relocation = a + Elf32_Addr(_segment); // Shift by main offset @@ -80,13 +81,36 @@ bool ARMDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment) break; case R_ARM_CALL: - debug(8, "elfloader: R_ARM_CALL: PC-relative jump, ld takes care of necessary relocation work for us."); - break; - case R_ARM_JUMP24: - debug(8, "elfloader: R_ARM_JUMP24: PC-relative jump, ld takes care of all relocation work for us."); - break; + if (sym->st_shndx == SHN_ABS) { // Absolute symbols used in PC-relative instructions need to be relocated + // Extract the PC offset from the instruction + int32 pcOffset = *target; + pcOffset = (pcOffset & 0x00ffffff) << 2; + + if (pcOffset & 0x02000000) + pcOffset -= 0x04000000; + + // Shift by the segment offset + pcOffset -= Elf32_Addr(_segment); + // Check the relocated offset is valid for the instruction + if (pcOffset <= (int32)0xfe000000 || + pcOffset >= (int32)0x02000000) { + warning("elfloader: R_ARM_CALL/R_ARM_JUMP24: Out of range relocation i=%d, target=%p, pcOffset=%d", i, target, pcOffset); + free(rel); + return false; + } + + // Put the relocated offset back in the instruction + pcOffset >>= 2; + pcOffset &= 0x00ffffff; + + *target &= (uint32)0xff000000; + *target |= (uint32)pcOffset; + + debug(8, "elfloader: R_ARM_CALL/R_ARM_JUMP24: i=%d, origTarget=%x, target=%x", i, origTarget, *target); + } + break; case R_ARM_V4BX: debug(8, "elfloader: R_ARM_V4BX: No relocation calculation necessary."); break; diff --git a/backends/plugins/elf/elf-loader.cpp b/backends/plugins/elf/elf-loader.cpp index 5198fa8088..39f1f7dfa5 100644 --- a/backends/plugins/elf/elf-loader.cpp +++ b/backends/plugins/elf/elf-loader.cpp @@ -50,8 +50,7 @@ DLObject::DLObject() : DLObject::~DLObject() { discardSymtab(); - ELFMemMan.pluginDeallocate(_segment); - _segment = 0; + discardSegment(); } // Expel the symbol table from memory @@ -65,11 +64,12 @@ void DLObject::discardSymtab() { _symbol_cnt = 0; } -// Unload all objects from memory -void DLObject::unload() { - discardSymtab(); - - ELFMemMan.pluginDeallocate(_segment); +void DLObject::discardSegment() { + if (_segment) { + // Restore default protection before returning memory + protectMemory(_segment, _segmentSize, PF_R | PF_W); + deallocateMemory(_segment, _segmentSize); + } _segment = 0; _segmentSize = 0; @@ -77,6 +77,12 @@ void DLObject::unload() { _segmentVMA = 0; } +// Unload all objects from memory +void DLObject::unload() { + discardSymtab(); + discardSegment(); +} + bool DLObject::readElfHeader(Elf32_Ehdr *ehdr) { assert(_file); @@ -163,7 +169,7 @@ bool DLObject::readProgramHeaders(Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, Elf32_Half } bool DLObject::loadSegment(Elf32_Phdr *phdr) { - _segment = (byte *)ELFMemMan.pluginAllocate(phdr->p_align, phdr->p_memsz); + _segment = (byte *)allocateMemory(phdr->p_align, phdr->p_memsz); if (!_segment) { warning("elfloader: Out of memory."); @@ -402,6 +408,8 @@ bool DLObject::load() { return false; } + protectMemory(_segment, _segmentSize, phdr.p_flags); + return true; } @@ -488,4 +496,12 @@ void *DLObject::symbol(const char *name) { return 0; } +void *DLObject::allocateMemory(uint32 align, uint32 size) { + return ELFMemMan.pluginAllocate(align, size); +} + +void DLObject::deallocateMemory(void *ptr, uint32 size) { + ELFMemMan.pluginDeallocate(ptr); +} + #endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) */ diff --git a/backends/plugins/elf/elf-loader.h b/backends/plugins/elf/elf-loader.h index 17ca35482a..1730338807 100644 --- a/backends/plugins/elf/elf-loader.h +++ b/backends/plugins/elf/elf-loader.h @@ -68,6 +68,7 @@ protected: int loadSymbolTable(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr); bool loadStringTable(Elf32_Shdr *shdr); virtual void relocateSymbols(ptrdiff_t offset); + void discardSegment(); // architecture specific @@ -83,6 +84,9 @@ protected: // platform specific virtual void flushDataCache(void *ptr, uint32 len) const = 0; + virtual void *allocateMemory(uint32 align, uint32 size); + virtual void deallocateMemory(void *ptr, uint32 size); + virtual void protectMemory(void *ptr, uint32 len, int prot) const {}; public: DLObject(); diff --git a/backends/plugins/elf/mips-loader.cpp b/backends/plugins/elf/mips-loader.cpp index 47ae00a8ea..e1e62234d5 100644 --- a/backends/plugins/elf/mips-loader.cpp +++ b/backends/plugins/elf/mips-loader.cpp @@ -279,7 +279,7 @@ bool MIPSDLObject::loadSegment(Elf32_Phdr *phdr) { // We need to take account of non-allocated segment for shorts if (phdr->p_flags & PF_X) { // This is a relocated segment // Attempt to allocate memory for segment - _segment = (byte *)ELFMemMan.pluginAllocate(phdr->p_align, phdr->p_memsz); + _segment = (byte *)allocateMemory(phdr->p_align, phdr->p_memsz); if (!_segment) { warning("elfloader: Out of memory."); diff --git a/backends/plugins/posix/posix-provider.cpp b/backends/plugins/posix/posix-provider.cpp index b484842ea5..2537d596a6 100644 --- a/backends/plugins/posix/posix-provider.cpp +++ b/backends/plugins/posix/posix-provider.cpp @@ -22,7 +22,7 @@ #include "common/scummsys.h" -#if defined(DYNAMIC_MODULES) && defined(POSIX) +#if defined(DYNAMIC_MODULES) && defined(POSIX) && !defined(__3DS__) #include "backends/plugins/posix/posix-provider.h" #include "backends/plugins/dynamic-plugin.h" @@ -3986,6 +3986,13 @@ _mak_plugins= if test "$_dynamic_modules" = yes ; then echo_n "Checking whether building plugins is supported... " case $_host_os in + 3ds) + _elf_loader=yes + append_var DEFINES "-DUNCACHED_PLUGINS" +_mak_plugins=' +PLUGIN_LDFLAGS += -Wl,-T$(srcdir)/backends/plugins/3ds/plugin.ld -march=armv6k -mfloat-abi=hard +' + ;; amigaos) _plugin_prefix="lib" _plugin_suffix=".so" @@ -5576,6 +5583,9 @@ case $_host_os in esac case $_backend in + 3ds) + append_var DEFINES "-DPLUGIN_DIRECTORY=\\\"$datadir/plugins\\\"" + ;; openpandora) # Add ../plugins as a path so plugins can be found when running from a .PND. append_var DEFINES "-DPLUGIN_DIRECTORY=\\\"../plugins\\\"" |