CPCWiki forum

General Category => Programming => Topic started by: Norman on 13:14, 10 October 20

Title: Using Arkos Tracker 2 together with CPCTelera
Post by: Norman on 13:14, 10 October 20
Hello,

currently I'm trying to use AT2 to create music for my game written in C with CPCTelera, which only supports AT1 songs, so manual work is required to use AT2 songs with CPCTelera.
What I found is this topic: cpctelera arkos 2 conversion problem (https://www.cpcwiki.eu/forum/programming/cpctelera-arkos-2-conversion-problem/msg170091/#msg170091). However, I can't get the examples provided there to work.

Can anyone tell me which export settings to use in AT2 and how to integrate the exported song and AT2 player routines into my C project? That'd be really helpful.

Cheers
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Targhan on 13:33, 10 October 20
Even though I develop AT2, I don't know anything about CPC Telera. I'm sure @Arnaud (https://www.cpcwiki.eu/forum/index.php?action=profile;u=1424) or @teopl (https://www.cpcwiki.eu/forum/index.php?action=profile;u=2874) or someone else will be able to help you :).
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Arnaud on 07:49, 11 October 20
Hi,
i assume you have succesfully converted you song/fx with this tutorial an have a single assembly file :
https://www.julien-nevo.com/arkostracker/index.php/using-a-song-in-production-using-rasm/

After you have to make some assembly functions and song visible by C compiler, simply add these line :

GAMEMUSIC_START:
_GAMEMUSIC_START::   'LINE ADDED
...
SOUNDEFFECTS_SOUNDEFFECTS:
_SOUNDEFFECTS_SOUNDEFFECTS::  'LINE ADDED
...
_PLY_AKM_INITSOUNDEFFECTS::
PLY_AKM_INITSOUNDEFFECTS:   'LINE ADDED
...
DO SAME FOR OTHERS LINES


In the Arkos2_api.zip you will find :

It should be easy adapt this code to your own music/fx.




Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Norman on 11:21, 11 October 20
Thanks for your reply, Arnaud, at least I managed to get the program to compile with all player routines integrated.
I followed these tutorials:And adapted the source files you provided to my song, but whenever I call PlaySound(), it crashes:

#include <cpctelera.h>
#include <sound.h>

void main() {
   static u8 pattern = 0;
   cpct_disableFirmware();
   cpct_setVideoMode(1);
   InitSound();

   while (1) {
      cpct_drawSolidBox((u8*)(0xC000), pattern++, 8, 8);
      cpct_waitVSYNC();
      PlaySound();
   }
}

I also tried calling it at interrupt instead, but that doesn't work either. I've attached a "working" CPCTelera project if you'd kindly want to have a look at it.
Cheers
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Arnaud on 14:13, 11 October 20
Ok i forgot something important, read arguments from C calling function because they use __z88dk_callee:

Simply add these lines after these two functions in the asm code.

_PLY_AKM_PlaySoundEffect::
        ;Gets the address to the sound effect.
pop  af          ;; AF = Return address
pop  hl          ;; H Rubbish / L = Sound effect
pop  bc          ;; B = Volume / C = Channel
push af          ;; Save back return address in the stack to fullfill __z88dk_callee convention
ld   a, l        ;; A = Subsong index

_PLY_AKM_Init::
pop  af          ;; AF = Return address
pop  hl          ;; HL = Music address
pop  bc          ;; Rubbish  / C  = Subsong index (>=0)
push af          ;; Save back return address in the stack to fullfill __z88dk_callee convention
ld   a, c        ;; A = Subsong index


Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Norman on 14:58, 11 October 20
Thanks, that was missing, works like a charm now  :)

As a summary for anbody who needs this:I extended my little build script to do that (it's run from the project folder and assumes the game has the same name as the folder):

#!/bin/sh
export CPCT_PATH=/path-to/cpctelera-git/cpctelera
rasm="/path-to/rasm"
at2disark="/path-to/Arkos Tracker 2/tools/Disark"
name=$(basename $(pwd))

# Prepare Arkos Tracker 2 song.
${rasm} assets/CompileAT2Files.asm assets/UniversalAt2Files -s -sl -sq
"${at2disark}" assets/UniversalAt2Files.bin src/At2Files.asm --symbolFile assets/UniversalAt2Files.sym --sourceProfile sdcc
# Add assembly code to be conformant with __z88dk_callee
sed -i -e 's/_PLY_AKM_INIT::/_PLY_AKM_INIT::\npop af\npop hl\npop bc\npush af\nld a, c/g' -e 's/_PLY_AKM_PlaySoundEffect::/_PLY_AKM_PlaySoundEffect::\npop af\npop hl\npop bc\npush af\nld a,l\n/g' src/At2Files.asm

if [ "$1" = "clean" ]; then
  make clean
fi
if make; then
   # Run disk image with mame or any other emulator.
   mame cpc6128 -flop1 ${name}.dsk -skip_gameinfo -noconfirm_quit -autoboot_delay 1 -autoboot_command "run\"${name}\n"
fi



Cheers
Edit: @Arnaud (https://www.cpcwiki.eu/forum/index.php?action=profile;u=1424), one more question. How can I play music in an interrupt if my game loop takes a varying amount of time? If I just put the PlaySound() function in the interrupt, it plays way too fast.
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Arnaud on 16:13, 11 October 20
Quote from: Norman on 14:58, 11 October 20Edit: @Arnaud (https://www.cpcwiki.eu/forum/index.php?action=profile;u=1424), one more question. How can I play music in an interrupt if my game loop takes a varying amount of time? If I just put the PlaySound() function in the interrupt, it plays way too fast.

Your song runs à 50hz and the interrupt works at 300hz just make a static counter and play it once every 6 ticks.

Here my interruption function :

void sInterruptHandler(void) {
    static u8 sInterrupt = 0;

    if (sInterrupt == 0)    {
        cpct_scanKeyboard_i();
    }
    else if (sInterrupt == 1)    {
        PlaySound();
    }
    else if
...

    if (++sInterrupt == 6)    {
        sInterrupt = 0;
    }
}
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Norman on 16:21, 11 October 20
 :picard: I should've known that. Thanks!
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Norman on 18:23, 11 October 20
Sorry for bothering you yet again, but I'm encountering another problem. When I play music in the interrupt and don't do much otherwise (e.g. main menu) everything seems fine. However, as soon as I run the game loop and play sound in the interrupt, it crashes the program (undefined/random behavior). I'm not doing anything fancy in my code, so it seems like calling CPU-heavy CPCTelera functions, like decompressing data, rendering a full tilemap etc. causes the crashes.

How could I go about debugging this?

Cheers
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Targhan on 21:42, 11 October 20
Two ideas:
- Are you sure you save ALL the registers in your interruption handler (including AF', IX, IY and all the other secondary registers). Don't forget AF.
- Maybe Cpctelera performs some bank switching, making the music player and/or data not available?
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Norman on 16:16, 13 October 20
Thanks for the suggestions Targhan, I'm going to have a closer look at these.
At worst (as in: time runs out), I'll only play music in the menu  :)
Cheers
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: SpDizzy on 18:03, 14 October 20
As @Targhan (https://www.cpcwiki.eu/forum/index.php?action=profile;u=110) said, those crashes and undefined/random behavior has to be with not saving registers before calling the player, so they are destroyed during this call. It's not CPCTelera related, but assembly call related. Make sure to save your registers (pushing to the stack) before call _PLY_AKM_PLAY and revert back (poping them) for perfect working during game loop.
Quick and dirty implementation (as inline asm on your sound.c file):
void PlaySound()
{
   ActivateMusic();
   //ActivateSFX();
__asm
     ;; Save registers before calling PLY_AKM_PLAY     
      exx
      ex af',af
      push af
      push bc
      push de
      push hl

      call _PLY_AKM_PLAY

    ;; Revert back registers after calling
      pop hl
      pop de
      pop bc
      pop af
      ex af',af
      exx
__endasm;

   //PLY_AKM_PLAY();
}

Good luck with the contest!!
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Norman on 19:02, 14 October 20
Beautiful, that did the trick. Thanks @SpDizzy (https://www.cpcwiki.eu/forum/index.php?action=profile;u=2740) for helping out an assembly noob!
Thanks, I'll probably need that luck because I'm getting anxious to fall behind on "schedule"  :)

Cheers
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: SpDizzy on 19:12, 14 October 20
Glad to help, but ¡beware! I'm just an assembly noob too! :)There's still time until November,3. Just do your best
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Targhan on 23:22, 14 October 20
Watch out, this looks dangerous to me. I strongly suggest that, if the player is called in your handler interruption, you save ALL the registers. The code @SpDizzy (https://www.cpcwiki.eu/forum/index.php?action=profile;u=2740) kindly provided only saves the auxiliary registers. Please also save the primary registers and IX/IY too! Else, hell awaits you :).

If this were your subroutine, you would know exactly what registers you would modify (sometimes only AF, and HL for example). But when calling a third party code (such as a music player), don't take any risk and save everything. This will save you hours of debugging.
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: SpDizzy on 08:32, 15 October 20
@Targhan (https://www.cpcwiki.eu/forum/index.php?action=profile;u=110) is true, mine was an incomplete solution working under this concrete example, but a risky approach to fit any case. Better save all registers to be safe
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Norman on 15:22, 15 October 20
Thanks @Targhan (https://www.cpcwiki.eu/forum/index.php?action=profile;u=110), added that now. So far, I didn't notice anything wrong, but it would've bitten me some time, so yeah  :)
That's another 58 cycles...  ;)

Cheers

Edit: For comprehension of the code, why are the registers first swapped with the shadow registers (2nd set) and then pushed onto the stack? (with exx and ex af,af', then push...)
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Targhan on 22:27, 15 October 20
QuoteFor comprehension of the code, why are the registers first swapped with the shadow registers

The original code only stored the auxiliary registers. You cannot PUSH DE', etc. directly, so you have to swap, store DE. If you save all the registers, no need to double-swap by the way. There is no "real" primary and auxiliary registers.
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: SpDizzy on 22:36, 15 October 20
QuoteEdit: For comprehension of the code, why are the registers first swapped with the shadow registers (2nd set) and then pushed onto the stack?

Well... since there are no opcodes for pushing or popping auxiliary/shadow registers, that's the way to go. Swapping them with primary ones, do the job with those, and swap again. But remember to save also primary and index ones, and in doubt, always thrust @Targhan (https://www.cpcwiki.eu/forum/index.php?action=profile;u=110) . God bless Arkos Tracker!
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Arnaud on 10:13, 17 October 20
@Norman (https://www.cpcwiki.eu/forum/index.php?action=profile;u=3845) If you don't use alternate registers, CPCTelera cpct_setInterruptHandler will save and restore all default registers.

Have you find your bug ?
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Norman on 10:26, 17 October 20
So CPCTelera saves and restores all default (i.e. primary) registers when the interrupt is called? That would explain why it did work even without saving ix and iy manually (as @Targhan (https://www.cpcwiki.eu/forum/index.php?action=profile;u=110) suggested)

As mentioned above, the crashes were caused by not saving the auxiliary registers before calling the player in the interrupt. Using the code @SpDizzy (https://www.cpcwiki.eu/forum/index.php?action=profile;u=2740) provided I could solve it.


Cheers
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Targhan on 16:05, 17 October 20
Uh ok, good to know. Couldn't have guessed, as I don't know Cpctelera :).
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: ronaldo on 10:43, 18 October 20
Quote from: Targhan on 16:05, 17 October 20
Uh ok, good to know. Couldn't have guessed, as I don't know Cpctelera :) .
Just for the record, @Targhan (https://www.cpcwiki.eu/forum/index.php?action=profile;u=110) , CPCtelera is not a maker but a framework. It includes compilers, tools and a low-level library, but nothing included is mandatory to be used. You can use everything in there up to your needs. You can just start a blank project and write assembly, machine code or C from scratch. So, effectively, CPCtelera is not an entity that "does" things. CPCtelera does nothing. When developers use the low-level library included, there are a bunch a functions and those have their own inner workings, as expected from every function. Then, it is appropriate to say that "function X from CPCtelera does Y", but not CPCtelera.

So, integrating any Amstrad-related source code into CPCtelera (such as Arkos 2) is the same as integrating it in any Amstrad production using any other tool. CPCtelera includes SDCC and ASZ80 as compiler and assembler. If you are able to convert code to ASZ80, you can then include it as source and assemble it along with your project files with ASZ80. If not, you can always include it in binary form.

So, as in any other developer adventure, CPCtelera makes no difference. It is just a bunch of development tools with some level of coordination between then that you can freely use up to your needs.

And this is why people can integrate your Arkos2 sources and/or binaries in CPCtelera, as they can also do it with any other source/binary.

Hope this helps better understanding it :)
Title: Re: Using Arkos Tracker 2 together with CPCTelera
Post by: Targhan on 10:54, 18 October 20
Thanks for the clarification :).
Powered by SMFPacks Menu Editor Mod