Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ The Authors
- Thomas Pfaff <tpfaff@tp76.info>
* OpenBSD sndio driver

- Alfonso Ranieri, codesets.library Open Source Team
* Amiga StackSwap assembly routine

- Alice Rowan <petrifiedrowan@gmail.com>
* Various features, sound driver enhancements and fixes

- Johan Samuelsson <spot@triad.se>
* Amiga port and fixes

Expand Down
4 changes: 4 additions & 0 deletions Changelog
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Stable versions
sndio, WinMM, AIFF, file, WAV.
- Use XMP_MAX_SRATE as the limit for -f instead of 48000
(requires libxmp 4.7.0+).
- Amiga: automatically expand stack via stack cookie (OS 4),
NewStackSwap (AROS), or StackSwap (Workbench 2.04+). The
Workbench and AROS behavior can be disabled by defining
XMP_NO_STACKSWAP.
- Report pan value "---" for instruments/samples without
a default panning value (sub->pan < 0).
- Don't unmute muted IT channels unless explicitly unmuted by
Expand Down
5 changes: 3 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ bin_PROGRAMS = xmp

xmp_SOURCES = \
commands.c common.h delay.c getopt_long.h getopt_long.c info.c \
main.c options.c read_config.c sound.c sound.h sound_file.c sound_null.c \
sound_wav.c sound_aiff.c terminal.c util.c xmp_version.h
main.c main_amiga.h options.c read_config.c sound.c sound.h \
sound_aiff.c sound_file.c sound_null.c sound_wav.c terminal.c util.c \
xmp_version.h
xmp_LDADD = ${LIBXMP_LIBS}
xmp_LDFLAGS = ${XMP_DARWIN_LDFLAGS}

Expand Down
1 change: 1 addition & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#if defined(XMP_AMIGA)
#include <proto/timer.h>
#include <time.h>
#include "main_amiga.h"
#endif
#if defined(__WATCOMC__)
#include <time.h>
Expand Down
183 changes: 183 additions & 0 deletions src/main_amiga.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/***************************************************************************

codesets.library - Amiga shared library for handling different codesets
Copyright (C) 2001-2005 by Alfonso [alfie] Ranieri <alforan@tin.it>.
Copyright (C) 2005-2021 codesets.library Open Source Team

Extended Module Player modifications:
Copyright (C) 2026 Lachesis <petrifiedrowan@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library 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
Lesser General Public License for more details.

codesets.library project: http://sourceforge.net/projects/codesetslib/

***************************************************************************/

/* Workbench, AmigaOS, AROS, MorphOS require manually setting the
* size of the stack. Include in main.c and nowhere else.
* Partially based on libinit.c code from codesets.library.
*
* Define XMP_NO_STACKSWAP to disable StackSwap/NewStackSwap/NewPPCStackSwap.
*/
#ifndef XMP_MAIN_AMIGA_H
#define XMP_MAIN_AMIGA_H

#include "common.h"

#if defined(XMP_AMIGA)

#include <proto/exec.h>

#if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 1))
#define XMP_USED __attribute__((used))
#else
#define XMP_USED
#endif

#define MIN_STACK_SIZE 32768

/* AmigaOS 3.2, 4.x */
extern const char stack_cookie[];
const char XMP_USED stack_cookie[] = "$STACK: 32768";

/* libnix, when swapstack.o is included (must be located manually...). */
extern int __stack;
int XMP_USED __stack = MIN_STACK_SIZE;

/* Workbench 2.04 through 3.1: manually set stack size via StackSwap.
* This needs to be performed through inline ASM to be safe.
*
* AROS: use NewStackSwap instead.
* MorphOS: use NewPPCStackSwap instead.
*/
#if !defined(__amigaos4__) && !defined(XMP_NO_STACKSWAP)

int real_main(int argc, char **argv);

/* The inline ASM from codesets.library expects one function argument, so
* it's easier to just use its semantics for now instead of rewriting it. */
struct main_args
{
int argc;
char **argv;
};

static ULONG main_wrapper(struct main_args *args)
{
return (ULONG)real_main(args->argc, args->argv);
}

#if defined(__mc68000__) && !defined(__AROS__)

ULONG xmp_stackswap_call(struct StackSwapStruct *stack,
ULONG (*main_fn)(struct main_args *args),
struct main_args *args);

asm(" .text \n\
.even \n\
.globl _xmp_stackswap_call \n\
_xmp_stackswap_call: \n\
moveml #0x3022,sp@- \n\
movel sp@(20),d3 \n\
movel sp@(24),a2 \n\
movel sp@(28),d2 \n\
movel _SysBase,a6 \n\
movel d3,a0 \n\
jsr a6@(-732:W) \n\
movel d2,sp@- \n\
jbsr a2@ \n\
movel d0,d2 \n\
addql #4,sp \n\
movel _SysBase,a6 \n\
movel d3,a0 \n\
jsr a6@(-732:W) \n\
movel d2,d0 \n\
moveml sp@+,#0x440c \n\
rts"
);

#elif defined(__AROS__)

static ULONG xmp_stackswap_call(struct StackSwapStruct *stack,
ULONG (*main_fn)(struct main_args *args),
struct main_args *args)
{
struct StackSwapArgs sa;

sa.Args[0] = (IPTR)args;

return NewStackSwap(stack, main_fn, &sa);
}

#elif defined(__MORPHOS__)

static ULONG xmp_stackswap_call(struct StackSwapStruct *stack,
ULONG (*main_fn)(struct main_args *args),
struct main_args *args)
{
struct PPCStackSwapArgs sa;

sa.Args[0] = (IPTR)args;

return NewPPCStackSwap(stack, main_fn, &sa);
}

#else
#error Unknown Amiga OS variant
#endif

int main(int argc, char **argv)
{
struct StackSwapStruct sw;
struct Task *tc;
ULONG sz;

tc = FindTask(NULL);

#ifdef __MORPHOS__
NewGetTaskAttrsA(tc, &sz, sizeof(ULONG), TASKINFOTYPE_STACKSIZE, NULL);
#else
sz = (UBYTE *)tc->tc_SPUpper - (UBYTE *)tc->tc_SPLower;
#endif

if (sz < MIN_STACK_SIZE) {
sw.stk_Lower = AllocVec(MIN_STACK_SIZE, MEMF_PUBLIC);
if (sw.stk_Lower != NULL) {
struct main_args args;
int ret;

sw.stk_Upper = (ULONG)sw.stk_Lower + MIN_STACK_SIZE;
sw.stk_Pointer = (APTR)sw.stk_Upper;

/*
printf("Swapping stack to size %d...\n", MIN_STACK_SIZE);
fflush(stdout);
*/

args.argc = argc;
args.argv = argv;
ret = (int)xmp_stackswap_call(&sw, main_wrapper, &args);

FreeVec(sw.stk_Lower);
return ret;
}
}

return real_main(argc, argv);
}

#define main real_main

#endif /* !AmigaOS4 && !defined(XMP_NO_STACKSWAP) */

#endif /* XMP_AMIGA */

#endif /* XMP_MAIN_AMIGA_H */
Loading