|
| 1 | +/*************************************************************************** |
| 2 | +
|
| 3 | + codesets.library - Amiga shared library for handling different codesets |
| 4 | + Copyright (C) 2001-2005 by Alfonso [alfie] Ranieri <alforan@tin.it>. |
| 5 | + Copyright (C) 2005-2021 codesets.library Open Source Team |
| 6 | +
|
| 7 | + Extended Module Player modifications: |
| 8 | + Copyright (C) 2026 Lachesis <petrifiedrowan@gmail.com> |
| 9 | +
|
| 10 | + This library is free software; you can redistribute it and/or |
| 11 | + modify it under the terms of the GNU Lesser General Public |
| 12 | + License as published by the Free Software Foundation; either |
| 13 | + version 2.1 of the License, or (at your option) any later version. |
| 14 | +
|
| 15 | + This library is distributed in the hope that it will be useful, |
| 16 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 18 | + Lesser General Public License for more details. |
| 19 | +
|
| 20 | + codesets.library project: http://sourceforge.net/projects/codesetslib/ |
| 21 | +
|
| 22 | + $Id$ |
| 23 | +
|
| 24 | +***************************************************************************/ |
| 25 | + |
| 26 | +/* Workbench, AmigaOS, AROS, MorphOS require manually setting the |
| 27 | + * size of the stack. Include in main.c and nowhere else. |
| 28 | + * Partially based on libinit.c code from codesets.library. |
| 29 | + * |
| 30 | + * Define XMP_NO_STACKSWAP to disable StackSwap/NewStackSwap/NewPPCStackSwap. |
| 31 | + */ |
| 32 | +#ifndef XMP_MAIN_AMIGA_H |
| 33 | +#define XMP_MAIN_AMIGA_H |
| 34 | + |
| 35 | +#include "common.h" |
| 36 | + |
| 37 | +#if defined(XMP_AMIGA) |
| 38 | + |
| 39 | +#include <proto/exec.h> |
| 40 | + |
| 41 | +#if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 1)) |
| 42 | +#define XMP_USED __attribute__((used)) |
| 43 | +#else |
| 44 | +#define XMP_USED |
| 45 | +#endif |
| 46 | + |
| 47 | +#define MIN_STACK_SIZE 32768 |
| 48 | + |
| 49 | +/* AmigaOS 3.2, 4.x */ |
| 50 | +extern const char stack_cookie[]; |
| 51 | +const char XMP_USED stack_cookie[] = "$STACK: 32768"; |
| 52 | + |
| 53 | +/* libnix, when swapstack.o is included (must be located manually...). */ |
| 54 | +extern int __stack; |
| 55 | +int XMP_USED __stack = MIN_STACK_SIZE; |
| 56 | + |
| 57 | +/* Workbench 2.04 through 3.1: manually set stack size via StackSwap. |
| 58 | + * This needs to be performed through inline ASM to be safe. |
| 59 | + * |
| 60 | + * AROS: use NewStackSwap instead. |
| 61 | + * MorphOS: use NewPPCStackSwap instead. |
| 62 | + */ |
| 63 | +#if !defined(__amigaos4__) && !defined(XMP_NO_STACKSWAP) |
| 64 | + |
| 65 | +int real_main(int argc, char **argv); |
| 66 | + |
| 67 | +/* The inline ASM from codesets.library expects one function argument, so |
| 68 | + * it's easier to just use its semantics for now instead of rewriting it. */ |
| 69 | +struct main_args |
| 70 | +{ |
| 71 | + int argc; |
| 72 | + char **argv; |
| 73 | +}; |
| 74 | + |
| 75 | +static ULONG main_wrapper(struct main_args *args) |
| 76 | +{ |
| 77 | + return (ULONG)real_main(args->argc, args->argv); |
| 78 | +} |
| 79 | + |
| 80 | +#if defined(__mc68000__) && !defined(__AROS__) |
| 81 | + |
| 82 | +ULONG xmp_stackswap_call(struct StackSwapStruct *stack, |
| 83 | + ULONG (*main_fn)(struct main_args *args), |
| 84 | + struct main_args *args); |
| 85 | + |
| 86 | +asm(" .text \n\ |
| 87 | + .even \n\ |
| 88 | + .globl _xmp_stackswap_call \n\ |
| 89 | +_xmp_stackswap_call: \n\ |
| 90 | + moveml #0x3022,sp@- \n\ |
| 91 | + movel sp@(20),d3 \n\ |
| 92 | + movel sp@(24),a2 \n\ |
| 93 | + movel sp@(28),d2 \n\ |
| 94 | + movel _SysBase,a6 \n\ |
| 95 | + movel d3,a0 \n\ |
| 96 | + jsr a6@(-732:W) \n\ |
| 97 | + movel d2,sp@- \n\ |
| 98 | + jbsr a2@ \n\ |
| 99 | + movel d0,d2 \n\ |
| 100 | + addql #4,sp \n\ |
| 101 | + movel _SysBase,a6 \n\ |
| 102 | + movel d3,a0 \n\ |
| 103 | + jsr a6@(-732:W) \n\ |
| 104 | + movel d2,d0 \n\ |
| 105 | + moveml sp@+,#0x440c \n\ |
| 106 | + rts" |
| 107 | +); |
| 108 | + |
| 109 | +#elif defined(__AROS__) |
| 110 | + |
| 111 | +static ULONG xmp_stackswap_call(struct StackSwapStruct *stack, |
| 112 | + ULONG (*main_fn)(struct main_args *args), |
| 113 | + struct main_args *args); |
| 114 | +{ |
| 115 | + struct StackSwapArgs sa; |
| 116 | + |
| 117 | + sa.Args[0] = (IPTR)args; |
| 118 | + |
| 119 | + return NewStackSwap(stack, main_fn, &sa); |
| 120 | +} |
| 121 | + |
| 122 | +#elif defined(__MORPHOS__) |
| 123 | + |
| 124 | +static ULONG xmp_stackswap_call(struct StackSwapStruct *stack, |
| 125 | + ULONG (*main_fn)(struct main_args *args), |
| 126 | + struct main_args *args); |
| 127 | +{ |
| 128 | + struct PPCStackSwapArgs sa; |
| 129 | + |
| 130 | + sa.Args[0] = (IPTR)args; |
| 131 | + |
| 132 | + return NewPPCStackSwap(stack, main_fn, &sa); |
| 133 | +} |
| 134 | + |
| 135 | +#else |
| 136 | +#error Unknown Amiga OS variant |
| 137 | +#endif |
| 138 | + |
| 139 | +int main(int argc, char **argv) |
| 140 | +{ |
| 141 | + struct StackSwapStruct sw; |
| 142 | + struct Task *tc; |
| 143 | + ULONG sz; |
| 144 | + |
| 145 | + tc = FindTask(NULL); |
| 146 | + |
| 147 | +#ifdef __MORPHOS__ |
| 148 | + NewGetTaskAttrsA(tc, &sz, sizeof(ULONG), TASKINFOTYPE_STACKSIZE, NULL); |
| 149 | +#else |
| 150 | + sz = (UBYTE *)tc->tc_SPUpper - (UBYTE *)tc->tc_SPLower; |
| 151 | +#endif |
| 152 | + |
| 153 | + if (sz < MIN_STACK_SIZE) { |
| 154 | + sw.stk_Lower = AllocVec(MIN_STACK_SIZE, MEMF_PUBLIC); |
| 155 | + if (sw.stk_Lower != NULL) { |
| 156 | + struct main_args args; |
| 157 | + int ret; |
| 158 | + |
| 159 | + sw.stk_Upper = (ULONG)sw.stk_Lower + MIN_STACK_SIZE; |
| 160 | + sw.stk_Pointer = (APTR)sw.stk_Upper; |
| 161 | + |
| 162 | + /* |
| 163 | + printf("Swapping stack to size %d...\n", MIN_STACK_SIZE); |
| 164 | + fflush(stdout); |
| 165 | + */ |
| 166 | + |
| 167 | + args.argc = argc; |
| 168 | + args.argv = argv; |
| 169 | + ret = (int)xmp_stackswap_call(&sw, main_wrapper, &args); |
| 170 | + |
| 171 | + FreeVec(sw.stk_Lower); |
| 172 | + return ret; |
| 173 | + } |
| 174 | + } |
| 175 | + |
| 176 | + return real_main(argc, argv); |
| 177 | +} |
| 178 | + |
| 179 | +#define main real_main |
| 180 | + |
| 181 | +#endif /* !AmigaOS4 && !defined(XMP_NO_STACKSWAP) */ |
| 182 | + |
| 183 | +#endif /* XMP_AMIGA */ |
| 184 | + |
| 185 | +#endif /* XMP_MAIN_AMIGA_H */ |
0 commit comments