From 83ebddc748e3d38d999ac6a17216cf1e5455c6cc Mon Sep 17 00:00:00 2001 From: Miro Kropacek Date: Sun, 19 Apr 2026 10:17:59 +1000 Subject: [PATCH] BACKENDS: ATARI: Implement plugins --- backends/module.mk | 5 + backends/platform/atari/atari.mk | 18 +- backends/platform/atari/build-release.sh | 11 +- backends/platform/atari/build-release030.sh | 11 +- backends/platform/atari/osystem_atari.cpp | 7 + backends/platform/atari/readme.txt | 10 +- backends/platform/atari/readme.txt.in | 10 +- backends/plugins/atari/atari-provider.cpp | 87 ++++++++++ backends/plugins/atari/atari-provider.h | 36 ++++ backends/plugins/elf/elf-loader.cpp | 3 + backends/plugins/elf/elf32.h | 10 ++ backends/plugins/elf/m68k-loader.cpp | 120 +++++++++++++ backends/plugins/elf/m68k-loader.h | 39 +++++ backends/plugins/firebee/firebee-provider.cpp | 91 ++++++++++ backends/plugins/firebee/firebee-provider.h | 36 ++++ backends/plugins/mintelf/plugin.ld | 163 ++++++++++++++++++ base/plugins.cpp | 6 +- configure | 19 +- 18 files changed, 658 insertions(+), 24 deletions(-) create mode 100644 backends/plugins/atari/atari-provider.cpp create mode 100644 backends/plugins/atari/atari-provider.h create mode 100644 backends/plugins/elf/m68k-loader.cpp create mode 100644 backends/plugins/elf/m68k-loader.h create mode 100644 backends/plugins/firebee/firebee-provider.cpp create mode 100644 backends/plugins/firebee/firebee-provider.h create mode 100644 backends/plugins/mintelf/plugin.ld diff --git a/backends/module.mk b/backends/module.mk index e6b2daa873a..4fb973b353e 100644 --- a/backends/module.mk +++ b/backends/module.mk @@ -173,6 +173,7 @@ MODULE_OBJS += \ plugins/elf/cxa-atexit.o \ plugins/elf/elf-loader.o \ plugins/elf/elf-provider.o \ + plugins/elf/m68k-loader.o \ plugins/elf/memory-manager.o \ plugins/elf/mips-loader.o \ plugins/elf/ppc-loader.o \ @@ -428,6 +429,10 @@ MODULE_OBJS += \ graphics/atari/atari-supervidel.o \ graphics/atari/atari-surface.o \ mixer/atari/atari-mixer.o +ifdef USE_ELF_LOADER +MODULE_OBJS += \ + plugins/atari/atari-provider.o +endif endif ifeq ($(BACKEND),ds) diff --git a/backends/platform/atari/atari.mk b/backends/platform/atari/atari.mk index 77bd28c47ed..e57cf8713ff 100644 --- a/backends/platform/atari/atari.mk +++ b/backends/platform/atari/atari.mk @@ -17,7 +17,7 @@ FB_DATA := ${FB_DIR} FB_DOCS := ${FB_DIR}/doc FB_THEMES := ${FB_DIR} -atarilitedist: $(EXECUTABLE) +atarilitedist: $(EXECUTABLE) plugins $(RM_REC) ${LITE_DIR} $(MKDIR) ${LITE_DIR} @@ -25,6 +25,13 @@ atarilitedist: $(EXECUTABLE) $(NM) -C ${LITE_DIR}/$(EXECUTABLE) | grep -vF ' .L' | grep ' [TtWV] ' | $(CXXFILT) | sort -u > ${LITE_DIR}/scummvm.sym $(STRIP) -s ${LITE_DIR}/$(EXECUTABLE) +ifneq ($(PLUGINS),) + $(MKDIR) ${LITE_DIR}/plugins + $(CP) $(PLUGINS) ${LITE_DIR}/plugins + $(STRIP) --strip-debug ${LITE_DIR}/plugins/*$(PLUGIN_SUFFIX) + ! [ -f ${LITE_DIR}/plugins/detection$(PLUGIN_SUFFIX) ] || mv ${LITE_DIR}/plugins/detection$(PLUGIN_SUFFIX) ${LITE_DIR}/plugins/detectio$(PLUGIN_SUFFIX) +endif + $(MKDIR) ${LITE_DOCS} $(CP) $(DIST_FILES_DOCS) ${LITE_DOCS} @@ -48,7 +55,7 @@ ifeq ($(CREATE_ZIP),y) $(ZIP) -r -9 ../${LITE_DIR}.zip ${LITE_DIR} endif -atarifulldist: $(EXECUTABLE) +atarifulldist: $(EXECUTABLE) plugins $(RM_REC) ${FULL_DIR} $(MKDIR) ${FULL_DIR} @@ -56,6 +63,13 @@ atarifulldist: $(EXECUTABLE) $(NM) -C ${FULL_DIR}/$(EXECUTABLE) | grep -vF ' .L' | grep ' [TtWV] ' | $(CXXFILT) | sort -u > ${FULL_DIR}/scummvm.sym $(STRIP) -s ${FULL_DIR}/$(EXECUTABLE) +ifneq ($(PLUGINS),) + $(MKDIR) ${FULL_DIR}/plugins + $(CP) $(PLUGINS) ${FULL_DIR}/plugins + $(STRIP) --strip-debug ${FULL_DIR}/plugins/*$(PLUGIN_SUFFIX) + ! [ -f ${FULL_DIR}/plugins/detection$(PLUGIN_SUFFIX) ] || mv ${FULL_DIR}/plugins/detection$(PLUGIN_SUFFIX) ${FULL_DIR}/plugins/detectio$(PLUGIN_SUFFIX) +endif + $(MKDIR) ${FULL_DOCS} $(CP) $(DIST_FILES_DOCS) ${FULL_DOCS} diff --git a/backends/platform/atari/build-release.sh b/backends/platform/atari/build-release.sh index d819bf02e5d..a8c1d6d5e7a 100755 --- a/backends/platform/atari/build-release.sh +++ b/backends/platform/atari/build-release.sh @@ -8,6 +8,7 @@ cd build-release PLATFORM=m68k-atari-mintelf FASTCALL=false +PLUGINS=true export ASFLAGS="-m68020-60" export CXXFLAGS="-m68020-60 -DUSE_MOVE16 -DUSE_SUPERVIDEL -DUSE_SV_BLITTER -DDISABLE_LAUNCHERDISPLAY_GRID" export LDFLAGS="-m68020-60" @@ -21,6 +22,13 @@ then LDFLAGS="$LDFLAGS -mfastcall" fi +if $PLUGINS +then + PLUGINS_FLAGS="--enable-plugins --default-dynamic --enable-detection-dynamic" +else + PLUGINS_FLAGS="" +fi + if [ ! -f config.log ] then ../configure \ @@ -28,7 +36,8 @@ then --host=${PLATFORM} \ --enable-release \ --enable-verbose-build \ - --disable-engine=hugo,director,cine,ultima,pink,wage + --disable-engine=hugo,director,cine,ultima,pink,wage \ + ${PLUGINS_FLAGS} fi make -j$(getconf _NPROCESSORS_CONF) atarifulldist diff --git a/backends/platform/atari/build-release030.sh b/backends/platform/atari/build-release030.sh index 80ec6781ef4..4c78cfee3e2 100755 --- a/backends/platform/atari/build-release030.sh +++ b/backends/platform/atari/build-release030.sh @@ -8,6 +8,7 @@ cd build-release030 PLATFORM=m68k-atari-mintelf FASTCALL=false +PLUGINS=true export ASFLAGS="-m68030" export CXXFLAGS="-m68030 -DDISABLE_FANCY_THEMES -DDISABLE_DOSBOX_OPL -DDISABLE_MAME_OPL" export LDFLAGS="-m68030" @@ -21,6 +22,13 @@ then LDFLAGS="$LDFLAGS -mfastcall" fi +if $PLUGINS +then + PLUGINS_FLAGS="--enable-plugins --default-dynamic --enable-detection-dynamic" +else + PLUGINS_FLAGS="" +fi + if [ ! -f config.log ] then ../configure \ @@ -30,7 +38,8 @@ then --disable-highres \ --disable-bink \ --enable-verbose-build \ - --disable-engine=hugo,director,cine,ultima + --disable-engine=hugo,director,cine,ultima \ + ${PLUGINS_FLAGS} fi make -j$(getconf _NPROCESSORS_CONF) atarilitedist diff --git a/backends/platform/atari/osystem_atari.cpp b/backends/platform/atari/osystem_atari.cpp index 527f7b10001..b2ec8429151 100644 --- a/backends/platform/atari/osystem_atari.cpp +++ b/backends/platform/atari/osystem_atari.cpp @@ -43,6 +43,9 @@ #include "backends/platform/atari/osystem_atari.h" #include "backends/audiocd/default/default-audiocd.h" +#ifdef DYNAMIC_MODULES +#include "backends/plugins/atari/atari-provider.h" +#endif #include "common/config-manager.h" #include "backends/events/atari/atari-events.h" #include "backends/events/default/default-events.h" @@ -522,6 +525,10 @@ int main(int argc, char *argv[]) { g_system = OSystem_Atari_create(); assert(g_system); +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new AtariPluginProvider()); +#endif + // Invoke the actual ScummVM main entry point: int res = scummvm_main(argc, argv); g_system->destroy(); diff --git a/backends/platform/atari/readme.txt b/backends/platform/atari/readme.txt index 199de1a38b3..504abf272b4 100644 --- a/backends/platform/atari/readme.txt +++ b/backends/platform/atari/readme.txt @@ -534,18 +534,10 @@ Future plans - DSP-based sample mixer (WAV, FLAC, MP2). -- Avoid loading music/speech files (and thus slowing down everything) if muted. - -- Cached audio/video streams (i.e. don't load only "audio_buffer_size" number - of samples but cache, say, 1 second so disk i/o won't be so stressed). - -- Using Thorsten Otto's sharedlibs: https://tho-otto.de/sharedlibs.php for game - engine plugins to relieve the huge binary size. +- Avoid decoding music/speech files (and thus slowing down everything) if muted. - True audio CD support via MetaDOS API. -- OPL2LPT and Retrowave support (if I manage to purchase it somewhere). - Closing words ------------- diff --git a/backends/platform/atari/readme.txt.in b/backends/platform/atari/readme.txt.in index d2a13d4119e..f0ec035feb3 100644 --- a/backends/platform/atari/readme.txt.in +++ b/backends/platform/atari/readme.txt.in @@ -534,18 +534,10 @@ Future plans - DSP-based sample mixer (WAV, FLAC, MP2). -- Avoid loading music/speech files (and thus slowing down everything) if muted. - -- Cached audio/video streams (i.e. don't load only "audio_buffer_size" number - of samples but cache, say, 1 second so disk i/o won't be so stressed). - -- Using Thorsten Otto's sharedlibs: https://tho-otto.de/sharedlibs.php for game - engine plugins to relieve the huge binary size. +- Avoid decoding music/speech files (and thus slowing down everything) if muted. - True audio CD support via MetaDOS API. -- OPL2LPT and Retrowave support (if I manage to purchase it somewhere). - Closing words ------------- diff --git a/backends/plugins/atari/atari-provider.cpp b/backends/plugins/atari/atari-provider.cpp new file mode 100644 index 00000000000..2c2aef4a91c --- /dev/null +++ b/backends/plugins/atari/atari-provider.cpp @@ -0,0 +1,87 @@ +/* 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 3 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, see . + * + */ + +#define FORBIDDEN_SYMBOL_ALLOW_ALL +#include "common/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(__MINT__) && defined(__ELF__) && !defined(__mcoldfire__) + +#include "backends/plugins/atari/atari-provider.h" +#include "backends/plugins/elf/m68k-loader.h" + +#include +#include +#include + +class AtariDLObject final : public M68KDLObject { +protected: + void relocateSymbols(ptrdiff_t offset) override { + // Symbols imported via `ld --just-symbols=$(EXECUTABLE)` (used by the + // plugin link step to resolve references into the main binary) end up as + // SHN_ABS with st_value = ELF VMA in the main binary. The atariprg loader + // loads the main binary at _base->p_tbase, so the runtime address is + // (ELF VMA + p_tbase). Patch SHN_ABS entries here; the base implementation + // then handles plugin-local symbols. + const uint32 mainOffset = (uint32)_base->p_tbase; + Elf32_Sym *s = _symtab; + for (uint32 c = _symbol_cnt; c--; s++) { + if (s->st_shndx == SHN_ABS) + s->st_value += mainOffset; + } + + DLObject::relocateSymbols(offset); + } + + void flushDataCache(void *ptr, uint32 len) const override { + if (Ssystem(-1, 0L, 0L) == 0) { + Ssystem(S_FLUSHCACHE, (long)ptr, (long)len); + } else { + long mcpu = 0; + + if (Getcookie(C__CPU, &mcpu) == C_FOUND) { + if (mcpu >= 40) { + long oldssp = Super(SUP_SET); + __asm__ volatile ( + ".word 0xF478\n\t" // cpusha dc + ".word 0xF498" // cinva ic + ::: "memory" + ); + Super((void *)oldssp); + } else if (mcpu >= 20) { + long oldssp = Super(SUP_SET); + __asm__ volatile ( + "movec %%cacr,%%d0\n\t" + "or.w #0x0008,%%d0\n\t" // CI + "movec %%d0,%%cacr" + ::: "d0", "cc", "memory" + ); + Super((void *)oldssp); + } + } + } + } +}; + +Plugin *AtariPluginProvider::createPlugin(const Common::FSNode &node) const { + return new TemplatedELFPlugin(node.getPath()); +} + +#endif // defined(DYNAMIC_MODULES) && defined(__MINT__) && defined(__ELF__) && !defined(__mcoldfire__) diff --git a/backends/plugins/atari/atari-provider.h b/backends/plugins/atari/atari-provider.h new file mode 100644 index 00000000000..fcc733906a6 --- /dev/null +++ b/backends/plugins/atari/atari-provider.h @@ -0,0 +1,36 @@ +/* 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 3 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, see . + * + */ + +#if defined(DYNAMIC_MODULES) && defined(__MINT__) && defined(__ELF__) && !defined(__mcoldfire__) + +#ifndef BACKENDS_PLUGINS_ATARI_PROVIDER_H +#define BACKENDS_PLUGINS_ATARI_PROVIDER_H + +#include "backends/plugins/elf/elf-provider.h" + +class AtariPluginProvider final : public ELFPluginProvider { +public: + Plugin *createPlugin(const Common::FSNode &node) const override; +}; + +#endif // BACKENDS_PLUGINS_ATARI_PROVIDER_H + +#endif // defined(DYNAMIC_MODULES) && defined(__MINT__) && defined(__ELF__) && !defined(__mcoldfire__) diff --git a/backends/plugins/elf/elf-loader.cpp b/backends/plugins/elf/elf-loader.cpp index 75469875c67..4be63738675 100644 --- a/backends/plugins/elf/elf-loader.cpp +++ b/backends/plugins/elf/elf-loader.cpp @@ -127,6 +127,9 @@ bool DLObject::readElfHeader(Elf32_Ehdr *ehdr) { #endif #ifdef PPC_TARGET EM_PPC +#endif +#ifdef M68K_TARGET + EM_68K #endif ) { warning("elfloader: Wrong ELF file architecture."); diff --git a/backends/plugins/elf/elf32.h b/backends/plugins/elf/elf32.h index c436922bc73..2d406ab230d 100644 --- a/backends/plugins/elf/elf32.h +++ b/backends/plugins/elf/elf32.h @@ -81,6 +81,7 @@ typedef struct { #define ET_CORE 4 /* core file */ // e_machine values +#define EM_68K 4 #define EM_MIPS 8 #define EM_PPC 20 #define EM_ARM 40 @@ -245,6 +246,15 @@ typedef struct { #define R_PPC_REL24 10 #define R_PPC_REL32 26 +// m68k relocation types +#define R_68K_NONE 0 +#define R_68K_32 1 +#define R_68K_16 2 +#define R_68K_8 3 +#define R_68K_PC32 4 +#define R_68K_PC16 5 +#define R_68K_PC8 6 + #endif // defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) #endif /* BACKENDS_ELF_H */ diff --git a/backends/plugins/elf/m68k-loader.cpp b/backends/plugins/elf/m68k-loader.cpp new file mode 100644 index 00000000000..1e520fa55a2 --- /dev/null +++ b/backends/plugins/elf/m68k-loader.cpp @@ -0,0 +1,120 @@ +/* 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 3 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, see . + * + */ + +#include "common/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(M68K_TARGET) + +#include "backends/plugins/elf/elf-loader.h" +#include "backends/plugins/elf/m68k-loader.h" + +#include "common/debug.h" + +#include + +bool M68KDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment) { + Elf32_Rela *rel = (Elf32_Rela *)malloc(size); + + if (!rel) { + warning("elfloader: Could not allocate %d bytes for the relocation table", size); + return false; + } + + if (!_file->seek(offset, SEEK_SET) || _file->read(rel, size) != size) { + warning("elfloader: Relocation table load failed."); + free(rel); + return false; + } + + uint32 cnt = size / sizeof(*rel); + + debug(2, "elfloader: Loaded relocation table. %d entries. base address=%p", cnt, relSegment); + + for (uint32 i = 0; i < cnt; i++) { + Elf32_Sym *sym = _symtab + REL_INDEX(rel[i].r_info); + byte *src = relSegment + rel[i].r_offset - _segmentVMA; + uint32 value = sym->st_value + rel[i].r_addend; + + switch (REL_TYPE(rel[i].r_info)) { + case R_68K_NONE: + break; + case R_68K_32: + *(uint32 *)src = value; + debug(8, "elfloader: R_68K_32 -> 0x%08x", *(uint32 *)src); + break; + case R_68K_16: + *(uint16 *)src = (uint16)value; + debug(8, "elfloader: R_68K_16 -> 0x%04x", *(uint16 *)src); + break; + case R_68K_8: + *src = (uint8)value; + debug(8, "elfloader: R_68K_8 -> 0x%02x", *src); + break; + case R_68K_PC32: + *(uint32 *)src = value - (uint32)src; + debug(8, "elfloader: R_68K_PC32 -> 0x%08x", *(uint32 *)src); + break; + case R_68K_PC16: + *(uint16 *)src = (uint16)(value - (uint32)src); + debug(8, "elfloader: R_68K_PC16 -> 0x%04x", *(uint16 *)src); + break; + case R_68K_PC8: + *src = (uint8)(value - (uint32)src); + debug(8, "elfloader: R_68K_PC8 -> 0x%02x", *src); + break; + default: + warning("elfloader: Unknown relocation type %d", REL_TYPE(rel[i].r_info)); + free(rel); + return false; + } + } + + free(rel); + return true; +} + +bool M68KDLObject::relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { + for (uint32 i = 0; i < ehdr->e_shnum; i++) { + Elf32_Shdr *curShdr = &(shdr[i]); + + if ((curShdr->sh_type == SHT_REL) && + curShdr->sh_entsize == sizeof(Elf32_Rel) && + int32(curShdr->sh_link) == _symtab_sect && + curShdr->sh_info < ehdr->e_shnum && + (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) { + warning("elfloader: REL entries not supported on m68k!"); + return false; + } + + if ((curShdr->sh_type == SHT_RELA) && + curShdr->sh_entsize == sizeof(Elf32_Rela) && + int32(curShdr->sh_link) == _symtab_sect && + curShdr->sh_info < ehdr->e_shnum && + (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) { + if (!relocate(curShdr->sh_offset, curShdr->sh_size, _segment)) + return false; + } + } + + return true; +} + +#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(M68K_TARGET) */ diff --git a/backends/plugins/elf/m68k-loader.h b/backends/plugins/elf/m68k-loader.h new file mode 100644 index 00000000000..fd67ca08774 --- /dev/null +++ b/backends/plugins/elf/m68k-loader.h @@ -0,0 +1,39 @@ +/* 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 3 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, see . + * + */ + +#ifndef BACKENDS_PLUGINS_M68K_LOADER_H +#define BACKENDS_PLUGINS_M68K_LOADER_H + +#include "common/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(M68K_TARGET) + +#include "backends/plugins/elf/elf-loader.h" + +class M68KDLObject : public DLObject { +protected: + bool relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment) override; + bool relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) override; +}; + +#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(M68K_TARGET) */ + +#endif /* BACKENDS_PLUGINS_M68K_LOADER_H */ diff --git a/backends/plugins/firebee/firebee-provider.cpp b/backends/plugins/firebee/firebee-provider.cpp new file mode 100644 index 00000000000..011c74cfacb --- /dev/null +++ b/backends/plugins/firebee/firebee-provider.cpp @@ -0,0 +1,91 @@ +/* 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 3 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, see . + * + */ + +#define FORBIDDEN_SYMBOL_ALLOW_ALL +#include "common/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(__MINT__) && defined(__ELF__) && defined(__mcoldfire__) + +#include "backends/plugins/firebee/firebee-provider.h" +#include "backends/plugins/elf/m68k-loader.h" + +#include +#include +#include + +class FireBeeDLObject final : public M68KDLObject { +protected: + void relocateSymbols(ptrdiff_t offset) override { + // Symbols imported via `ld --just-symbols=$(EXECUTABLE)` (used by the + // plugin link step to resolve references into the main binary) end up as + // SHN_ABS with st_value = ELF VMA in the main binary. The atariprg loader + // loads the main binary at _base->p_tbase, so the runtime address is + // (ELF VMA + p_tbase). Patch SHN_ABS entries here; the base implementation + // then handles plugin-local symbols. + const uint32 mainOffset = (uint32)_base->p_tbase; + Elf32_Sym *s = _symtab; + for (uint32 c = _symbol_cnt; c--; s++) { + if (s->st_shndx == SHN_ABS) + s->st_value += mainOffset; + } + + DLObject::relocateSymbols(offset); + } + + void flushDataCache(void *ptr, uint32 len) const override { + if (Ssystem(-1, 0L, 0L) == 0) { + Ssystem(S_FLUSHCACHE, (long)ptr, (long)len); + } else { + // ignored for now + (void)ptr; + (void)len; + + long oldssp = Super(SUP_SET); + __asm__ volatile ( + "nop\n\t" // flush store buffer + "moveq.l #0,%%d0\n\t" // way = 0 + "moveq.l #0,%%d1\n\t" // set = 0 + "move.l %%d0,%%a0\n" + "1:\n\t" + "cpushl %%bc,(%%a0)\n\t" // push + invalidate line + "add.l #16,%%a0\n\t" + "addq.l #1,%%d1\n\t" + "cmpi.l #512,%%d1\n\t" + "bne.s 1b\n\t" + "moveq.l #0,%%d1\n\t" + "addq.l #1,%%d0\n\t" + "move.l %%d0,%%a0\n\t" + "cmpi.l #4,%%d0\n\t" + "bne.s 1b" + : + : + : "d0", "d1", "a0", "memory", "cc" + ); + Super((void *)oldssp); + } + } +}; + +Plugin *FireBeePluginProvider::createPlugin(const Common::FSNode &node) const { + return new TemplatedELFPlugin(node.getPath()); +} + +#endif // defined(DYNAMIC_MODULES) && defined(__MINT__) && defined(__ELF__) && defined(__mcoldfire__) diff --git a/backends/plugins/firebee/firebee-provider.h b/backends/plugins/firebee/firebee-provider.h new file mode 100644 index 00000000000..0eabb690ef9 --- /dev/null +++ b/backends/plugins/firebee/firebee-provider.h @@ -0,0 +1,36 @@ +/* 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 3 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, see . + * + */ + +#if defined(DYNAMIC_MODULES) && defined(__MINT__) && defined(__ELF__) && defined(__mcoldfire__) + +#ifndef BACKENDS_PLUGINS_FIREBEE_PROVIDER_H +#define BACKENDS_PLUGINS_FIREBEE_PROVIDER_H + +#include "backends/plugins/elf/elf-provider.h" + +class FireBeePluginProvider final : public ELFPluginProvider { +public: + Plugin *createPlugin(const Common::FSNode &node) const override; +}; + +#endif // BACKENDS_PLUGINS_FIREBEE_PROVIDER_H + +#endif // defined(DYNAMIC_MODULES) && defined(__MINT__) && defined(__ELF__) && defined(__mcoldfire__) diff --git a/backends/plugins/mintelf/plugin.ld b/backends/plugins/mintelf/plugin.ld new file mode 100644 index 00000000000..29683d3b319 --- /dev/null +++ b/backends/plugins/mintelf/plugin.ld @@ -0,0 +1,163 @@ +/* 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 3 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, see . + * + */ + +OUTPUT_FORMAT("elf32-m68k") +OUTPUT_ARCH(m68k) +ENTRY(_start) + +PHDRS +{ + /* ScummVM's elf loader only allows a single segment. */ + plugin PT_LOAD FLAGS(7) /* Read | Write | Execute */; +} + +SECTIONS +{ + . = 0; + + .text ALIGN(4) : + { + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + } : plugin + + .rodata ALIGN(4) : + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r*) + *(.rodata1) + . = ALIGN(4); + } : plugin + + .preinit_array ALIGN(4) : + { + PROVIDE (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + } : plugin + + /* m68k-atari-mintelf gcc emits constructors into .init_array (and dtors + * into .fini_array). The ELF plugin loader walks ___plugin_ctors and + * ___plugin_dtors both forward; .init_array semantics match (ascending + * priority = construction order), but standard .fini_array is walked + * backward by a normal runtime, so we REVERSE the .fini_array sort here + * to get reverse-of-construction destruction order out of a forward + * walk. .ctors/.dtors are kept too in case any input object still uses + * the legacy sections. */ + .ctors ALIGN(4) : + { + ___plugin_ctors = .; + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*))) + KEEP (*(.init_array)) + KEEP (*(SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.ctors)) + ___plugin_ctors_end = .; + } : plugin + + .dtors ALIGN(4) : + { + ___plugin_dtors = .; + KEEP (*(SORT_BY_INIT_PRIORITY(REVERSE(.fini_array.*)))) + KEEP (*(.fini_array)) + KEEP (*(SORT_BY_INIT_PRIORITY(REVERSE(.dtors.*)))) + KEEP (*(.dtors)) + ___plugin_dtors_end = .; + } : plugin + + .data ALIGN(4) : + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + CONSTRUCTORS + . = ALIGN(4); + } : plugin + .data1 : + { + *(.data1) + . = ALIGN(4); + } : plugin + + __bss_start__ = .; + .bss ALIGN(4) : + { + *(.dynbss) + *(.bss) + *(SORT(.bss.*)) + *(.gnu.linkonce.b*) + *(COMMON) + . = ALIGN(4); + } : plugin + __bss_end__ = .; + + __end__ = ABSOLUTE(.) ; + + /* Discard sections that complicate 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) } + + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } +} diff --git a/base/plugins.cpp b/base/plugins.cpp index 5bdf09c5691..93aaa7bcbfd 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -318,7 +318,11 @@ void PluginManagerUncached::init() { unloadPluginsExcept(PLUGIN_TYPE_ENGINE, nullptr, false); // empty the engine plugins #ifndef DETECTION_STATIC - Common::String detectPluginName = "detection"; +#ifdef PLUGIN_DETECTION_NAME +Common::String detectPluginName = PLUGIN_DETECTION_NAME; +#else +Common::String detectPluginName = "detection"; +#endif #ifdef PLUGIN_SUFFIX detectPluginName += PLUGIN_SUFFIX; #endif diff --git a/configure b/configure index 97c8097738a..9a6f8c280e2 100755 --- a/configure +++ b/configure @@ -684,7 +684,7 @@ get_system_exe_extension() { mingw* | *os2-emx) _exeext=".exe" ;; - mint) + mint*) _exeext=".prg" ;; emscripten) @@ -1841,6 +1841,11 @@ kos32) _host_cpu=i686 _host_alias=kos32 ;; +m68k-atari-mintelf*) + _host_os=mintelf + _host_cpu=m68k + _host_alias=$_host + ;; m68k-atari-mint*) _host_os=mint _host_cpu=m68k @@ -5203,6 +5208,18 @@ PLUGIN_EXTRA_DEPS = PLUGIN_LDFLAGS += -shared PRE_OBJS_FLAGS := -Wl,-export-dynamic -Wl,-whole-archive POST_OBJS_FLAGS := -Wl,-no-whole-archive +' + ;; + mintelf) + _elf_loader=yes + append_var DEFINES "-DM68K_TARGET" + append_var DEFINES "-DPLUGIN_DETECTION_NAME=\\\"detectio\\\"" + append_var CXXFLAGS "-fuse-cxa-atexit" + append_var DEFINES "-DELF_LOADER_CXA_ATEXIT" + append_var DEFINES "-DUNCACHED_PLUGINS" + append_var DEFINES "-DELF_NO_MEM_MANAGER" +_mak_plugins=' +PLUGIN_LDFLAGS += -Wl,-m,m68kelf,-T,$(srcdir)/backends/plugins/mintelf/plugin.ld ' ;; *cygwin* | *mingw32* | mingw64)