Ultimate Amiga

Network Boards => AMOS Language Discussion => AMOS Factory => AMOS Professional Forum => Topic started by: zerina on May 17, 2013, 09:25:39 PM

Title: call playsid.library
Post by: zerina on May 17, 2013, 09:25:39 PM
Hi,

after years i back on amiga and trying to code with Amos.
I would like to play a SID file within my project, used the fd builder and created and bulided an amos extension to better comunicate with the playsid.library.

My task is realy simple, the programm should only play that sid file, but unfortunatly i wil not work.
Thes are the calls to the playsid.library i perfom
1) AllocEmulResource
2) Readicon
3) checkmodule
4) Setmodule
5) Playsong

Any help in starting with this would be great, probably someone had already included the playsid.library in his project and could share some ideas or code

regards


Title: Re: call playsid.library
Post by: Hungry Horace on May 19, 2013, 03:58:01 PM
tough question!

One of the resident AMOS extension experts (Lonewolf? Sidewinder?) is probably best-placed to answer this as they may have experience tapping specific Libraries via AMOS....
Title: Re: call playsid.library
Post by: SamuraiCrow on May 19, 2013, 07:43:43 PM
I've tried the FD Builder program before but I never got the resultant extensions to work.  Have you tried using the LibCall command?
Title: Re: call playsid.library
Post by: zerina on May 19, 2013, 10:38:53 PM
Well any kind of example would help,

using the fd builder an d accessing the library in basic actions works:
Code: [Select]
A=Lvo Allocemulresource()teh above  is fd builder style

Code: [Select]
Lib Open 1,"playsid.library",0The above is Lib Open style

When yyou ste further you need pointer and register, an thats the point where i currently struggle, i need an example to step further.
The playsid.libraray order is clear
1) AllocEmulResource
2) Readicon
3) checkmodule
4) Setmodule
5) Playsong

I simply need some help
Title: Re: call playsid.library
Post by: SamuraiCrow on May 20, 2013, 12:15:04 PM
If you know which registers to put the variables into you can use the Areg and Dreg commands to pass them into and out of the subroutines in the LibCall command.  Normally, values returned from the subroutines are in register D0.  Pointers, being returned are in the A0 register.  Most libraries are written for the C programming language and only return one value.

Case in point:
If the FD file or autodocs for the subroutine say that it takes a pointer in A0 and value1 in D0 and value2 in D1 but returns a handle as a pointer, the Libcall command would look like this:

Areg("A0")=pointer
Dreg("D0")=value1
Dreg("D1")=value2
LibCall(1,Lvo("subroutine_name"))
handle=Areg("A0")
Title: Re: call playsid.library
Post by: zerina on May 22, 2013, 09:40:08 PM
Hi,

thanks for the explanation,
Openng the Lib works
Calling AllocEmulRessource works, but as soon as i try to call the readicon funtion Amos/Amiga crashes

Thes are the function of playsid.library
Code: [Select]
struct PlaySidBase *PlaySidBase;


AllocEmulResource -30(-$001E)
wersja: V1
wej¶cie: void
rezultat: D0
opis:   Allocates and initilizes memory resources.
error=(LONG)AllocEmulResource( void );
D0

CheckModule -48(-$0030)
wersja: V1
wej¶cie: A0
rezultat: D0
opis:   Checks if supplied header is a valid playsid header.
One part files starts with the header.
error=(LONG)CheckModule( (APTR)header );
D0 A0

ContinueSong -78(-$004E)
wersja: V1
wej¶cie: void
rezultat: D0
opis:   Same as start except it is used to continue a paused song.
error=(LONG)ContinueSong( void );
D0

ForwardSong -84(-$0054)
wersja: V1
wej¶cie: D0
rezultat: void
opis:   Used to fast forward a currently playing song. The play routine
will be called as many times as given in the speed parameter.
void ForwardSong( (UWORD)speed );
D0.W

FreeEmulResource -36(-$0024)
wersja: V1
wej¶cie: void
rezultat: void
opis:   Frees memory resources.
void FreeEmulResource( void );

PauseSong -72(-$0048)
wersja: V1
wej¶cie: void
rezultat: void
opis:   Same as Stop except that the song could be continued afterwards.
void PauseSong( void );

ReadIcon -42(-$002A)
wersja: V1
wej¶cie: A0
A1
rezultat: D0
opis: Reads icon info of supplied name (without .info suffix)
and stores it at "header".
error=(LONG)ReadIcon( (char *)filename,(APTR)header );
D0 A0 A1

RewindSong -90(-$005A)
wersja: V1
wej¶cie: D0
rezultat: void
opis: Used to rewind a currently playing song. The play routine will
be called as many times as given in the speed parameter. The reverse
flag needs to be set!
void RewindSong( (UWORD)speed );
D0.W

SetChannelEnable -102(-$0066)
wersja: V1
wej¶cie: A0
rezultat: void
opis: Sets the status of the four channels. "flags" is a pointer to an
array of four boolean values (16 bits each).
void SetChannelEnable( (BOOL)flags[4] );
A0

SetDisplayEnable -132(-$0084)
wersja: V1
wej¶cie: D0
rezultat: void
opis: funkcja prywatna
void SetDisplayEnable( (BOOL)flag );
D0

SetDisplaySignal -126(-$007E)
wersja: V1
wej¶cie: A0
D0
rezultat: void
opis: funkcja prywatna
void SetDisplaySignal( (struct Task *)task,(ULONG)displayMask );
A0 D0

SetModule -54(-$0036)
wersja: V1
wej¶cie: A0
A1
D0
rezultat: void
opis:   Sets a new module. Next time a song is started this module is used.
In one part files the file location and header could be the same, becuase
the function skips the headers.
void SetModule( (APTR)header,(APTR)fileLocation,(UWORD)fileLength );
A0 A1 D0

SetReverseEnable -108(-$006C)
wersja: V1
wej¶cie: D0
rezultat: void
opis: Sets the status of the reverse flag.
void SetReverseEnable( (BOOL)flag );
D0.W

SetTimeEnable -120(-$0078)
wersja: V1
wej¶cie: D0
rezultat:
opis: funkcja prywatna
void SetTimeEnable( (BOOL)flag );
D0

SetTimeSignal -114(-$0072)
wersja: V1
wej¶cie: A0
D0
rezultat: void
opis: funkcja prywatna
void SetTimeSignal( (struct Task *)task,(ULONG)timeMask );
A0 D0

SetVertFreq -96(-$0060)
wersja: V1
wej¶cie: D0
rezultat: void
opis: Sets the simulated TV system frequence. 50Hz for PAL or 60Hz for NTSC.
void SetVertFreq( (UWORD)frequency );
D0.W

StartSong -60(-$003C)
wersja: V1
wej¶cie: D0
rezultat: D0
opis: Starts to play the supplied tune number. The audio device, timers
and interrupts are allocated.
error=(LONG)StartSong( (UWORD)tune );
D0 D0.W

StopSong -66(-$0042)
wersja: V1
wej¶cie: void
rezultat: void
opis:   Stops the current song. The audio device, timers and interrupts are freed.
void StopSong( void );

So Readicon takes
Code: [Select]
error=(LONG)ReadIcon( (char *)filename,(APTR)header );
D0 A0 A1
Thats where i fail / the programm crahes, can you pleas push me to the right direction.
Title: Re: call playsid.library
Post by: SamuraiCrow on May 23, 2013, 10:01:27 AM
Since the library is written in C and/or Assembly, some conventions are used that are different than AmosPro.  One example is string handling.  AmosPro, like many BASIC variations, stores the length of the string so that it doesn't have to recalculate it every time.  C doesn't do that.  It marks the end with a null character.  Because that is the case, you need a conversion function that will add the CHR$(0) on the end to create a null character and send the address of the first character to the function you need.

Also, if a function has a return code, you have to check that as well.  If it is properly handled, you may have to assign a function's return code to a variable.  If you're using the LVO wrapper, it might let you use the format:

Code: [Select]
FNAME$="Filename.sid"+Chr$(0)
Reserve As Bank Work 14, 124 ` allocate size of PlaySid header in bank 14
SIDHEAD=Start(14) ` copy the start address of the header into a variable
STATUS=Lvo Readicon(Varptr(FNAME$)+2, SIDHEAD) ` read the icon of filename.sid into the header.

By the way, I had to download PlaySid3 just to find the documentation needed to use the library.  It takes more than just functions, it takes structures also.
Title: Re: call playsid.library
Post by: zerina on May 24, 2013, 06:51:36 AM
Again thanks for your Help,

i have hacked some small code, it still crashes, now when calling the playsong function, all other calls deliver no error, so my guess is, that i reference the sid module false. so the pointer is wrong.

Code: [Select]
Erase All
A=_playsid Base()
If A=0
 Print "error"
End If
A=Lvo Allocemulresource()
M0DULE$=Fsel$("*.sid","","Load a ","SID Module")
M0DULE$=M0DULE$+Chr$(0)
Open Random 1,M0DULE$
M0DULE_LENGTH=Lof(1)
Close 1
If Chip Free<M0DULE_LENGTH
   Cls
   Centre "Not enough CHIP RAM.  Press any key to exit."
   Wait Key
End If
Reserve As Work 14,124
SIDHEAD=Start(14)
STATUS=Lvo Readicon(Varptr(M0DULE$),SIDHEAD)
Print STATUS
STATUS=Lvo Checkmodule(SIDHEAD)
Print STATUS

M0DULE_POINTER=Varptr(M0DULE$)
STATUS=Lvo Setmodule(SIDHEAD,M0DULE_POINTER,M0DULE_LENGTH)
Print STATUS

STATUS=Lvo Startsong(1)
Print STATUS
Wait Key
Title: Re: call playsid.library
Post by: SamuraiCrow on May 24, 2013, 08:59:25 AM
You need to add 2 to the location of VarPtr(MODULE$) because the length of the string is stored in the first two byte word of MODULE$.  I should have explained that earlier.
Title: Re: call playsid.library
Post by: zerina on May 24, 2013, 09:51:24 AM
I tested that but if doing so then the string is left cutted 2 chars
for example the string is "Amos:mytune.sid"
then when running the readicon function the system says
"Inset Volume os"
if removing the the +2 no error comes up.

Title: Re: call playsid.library
Post by: Lonewolf10 on May 24, 2013, 08:25:55 PM
Your error routine stops until you press a key. I suggest adding an End instruction (coloured green in the code below), for safety ;)
Are you sure that the bank you are reserving is large enough (highlighted in red)? Shouldn't that be replaced with MODULE_LENGTH, or is that purely for the header only??


If Chip Free<M0DULE_LENGTH
   Cls
   Centre "Not enough CHIP RAM.  Press any key to exit."
   Wait Key
   End
End If
Reserve As Work 14,124



Edit: Are you sure the bank is being reserved in Chip RAM and not fast RAM?
Title: Re: call playsid.library
Post by: SamuraiCrow on May 24, 2013, 10:34:26 PM
Bank 14, as my example allocated, was to be allocated in FAST RAM for use as the header only.

Edit:  @Lonewolf10: The SID file can be Fast RAM as well because SID files contain only 4-bit samples that have to be converted by the library in realtime.  The other 3 voices are synthesized in realtime by the library also thus all Chip RAM needed is allocated by the library itself, I would think.

@zebrina:
Where are you loading the SID file itself?
Title: Re: call playsid.library
Post by: Lonewolf10 on May 24, 2013, 11:48:33 PM
Bank 14, as my example allocated, was to be allocated in FAST RAM for use as the header only.

Ahh, I see.

Edit:  @Lonewolf10: The SID file can be Fast RAM as well because SID files contain only 4-bit samples that have to be converted by the library in realtime.  The other 3 voices are synthesized in realtime by the library also thus all Chip RAM needed is allocated by the library itself, I would think.

Ok :)
Title: Re: call playsid.library
Post by: zerina on May 25, 2013, 12:46:46 PM
Quote
Where are you loading the SID file itself?
well this is the part where the sid file is beeing selected and loaded

Code: [Select]
M0DULE$=Fsel$("*.sid","","Load a ","SID Module")
M0DULE$=M0DULE$+Chr$(0)
Open Random 1,M0DULE$
M0DULE_LENGTH=Lof(1)
Title: Re: call playsid.library
Post by: SamuraiCrow on May 25, 2013, 05:25:43 PM
I see that you open the file, find the length, and close it.  It never reads it into a bank after that.  Before you use LVO Setmodule you need to load the file into another bank with either a "Reserve as Work 15, MODULE_LENGTH:Bload module$, 15" or something similar from the library itself.
Title: Re: call playsid.library
Post by: zerina on May 25, 2013, 06:30:58 PM
Again thanks for your help,
i followed your advice and added your example Statement but it still crashes when calling the play.
Title: Re: call playsid.library
Post by: SamuraiCrow on May 25, 2013, 06:41:54 PM
LVO Setmodule is looking for the locaiton of the file, not the filename.  Your original code just pointed to the filename when calling it.  Set the second parameter of LVO Setmodule to be Start(15).
Title: Re: call playsid.library
Post by: zerina on May 25, 2013, 07:52:11 PM
Again you are right, but i allready played with start(15), still no joy......

While i was writing these lines i found the solution, the set module has to be called like this.
Code: [Select]
STATUS=Lvo Setmodule)Start(15),Start(15),M0DULE_LENGTH
The Documentation says
Quote
In one part files the file location and header could be the same, becuase the function skips the headers.
And now it works, thank you very much for your help

But SID file plays a bit to fast, faster than playing it from Workbench by using the sidplayer.

Title: Re: call playsid.library
Post by: Lonewolf10 on May 25, 2013, 08:32:14 PM
And now it works, thank you very much for your help

But SID file plays a bit to fast, faster than playing it from Workbench by using the sidplayer.

Are there any functions in the library that allow you to adjust the speed?
Title: Re: call playsid.library
Post by: SamuraiCrow on May 25, 2013, 08:55:00 PM
Try "LVO Setvertfreq(50)" before you play it.
Title: Re: call playsid.library
Post by: zerina on May 25, 2013, 09:16:52 PM
Guys finaly everything works  :D

"LVO Setvertfreq(50)" brought the right speed

i played with icon settings as mentioned in the readme, anyway  the LVO Setvertfreq(50) made it.

Funtastic help here !!!
regards


Title: Re: call playsid.library
Post by: SamuraiCrow on May 25, 2013, 10:32:33 PM
You're welcome!
Title: Re: call playsid.library
Post by: Hungry Horace on May 26, 2013, 12:43:03 AM
Any chance you cod post your working code, so that others might
A- have working SID files on Amos
B- maybe learn something about library calls in Amos!!!

Thanks!!
Title: Re: call playsid.library
Post by: zerina on May 26, 2013, 01:08:12 PM
Off course, i will post the code and some explanation
Title: Re: call playsid.library
Post by: zerina on May 26, 2013, 04:58:23 PM
Final Solution:
(only a small Example without any special error handling)

1) First off all you need the playsid.library and the fd file for the playsid.library
2) By using the FD Builder (can be found here in the Download Section) go an create an Amos-Extension fot the use of the playsid.library
3) Add this new Extension to your Amos enviroment

now add some code to your project.
4.) Open the Library
Code: [Select]
   Erase All
A=_playsid Base()
If A=0
 Print "error"
End If
5.) Init
Code: [Select]
A=Lvo Allocemulresource()6)Load a SID File
Code: [Select]
M0DULE$=Fsel$("*.sid","","Load a ","SID Module")
M0DULE$=M0DULE$+Chr$(0)
Open Random 1,M0DULE$
M0DULE_LENGTH=Lof(1)
Close 1

7) Reserve memory for the  header
Code: [Select]
Reserve As Work 14,124
SIDHEAD=Start(14)

8) Call Readicon
Code: [Select]
STATUS=Lvo Readicon(Varptr(M0DULE$),SIDHEAD)
9) Call Checkmodule
Code: [Select]
STATUS=Lvo Checkmodule(SIDHEAD)
10) Reserve a Bank and load the sid module
Code: [Select]
Reserve As Work 15,M0DULE_LENGTH : Bload M0DULE$,15
M0DULE_POINTER=Varptr(M0DULE$)

11) Call Setmodule
Code: [Select]
STATUS=Lvo Setmodule(Start(15),Start(15),M0DULE_LENGTH)
12) Call Setvertfreq (50=PAL)
Code: [Select]
STATUS=Lvo Setvertfreq(50)
13) Call Startsong(Play tune X)
Code: [Select]
STATUS=Lvo Startsong(1)
Off Course we need error handling and more functions linke Stopsong, and off course we need to close the lib etc.

BTW can we Build an Small extension wit functions included ?

Again thanks for all the help / support without this would never been possible.
Title: Re: call playsid.library
Post by: james666 on May 31, 2013, 11:05:46 PM
I've been going a little crazy thinking about AmosPro redevelopment so I thought I'd refresh my brain by creating something a bit more self-contained.  The attachment contains a simple extension that serves as a user-friendly AmosPro wrapper for the PlaySid.library.  playsid.lib needs to be copied to the APSystem directory and installed as extension number 20 in the interpreter.  (You can change the extension number if necessary by re-assembling the source.)  The new commands are as follows:

Psload filename, bank number  This loads the module, checks it and copies it to the specified memory bank.  Both header and data are copied to the same bank.  It should work whether the header is in a separate filename.icon file or contained in the main file.  After the bank is created, it can be saved and reloaded as a .abk file using the normal Save and Load commands.

=Psbanklength(bank number) returns the number of songs in the specified bank. 

Psplay bank number, song number plays the specified song.

Psstop stops the music.

Pspause pauses the music. 

Pscontinue resumes music after a Pspause.

Pssetvertfreq frequency can be used to adjust the frequency between PAL (50) and NTSC (60).

Pscloselib stops the music, closes playsid.library and frees its resources.  (The library is automatically opened when the first Ps command is used.)

Known issues: Amos will crash if you attempt to use the normal sound commands and playsid.library at the same time.  Normal sound commands should be OK if playsid is loaded but not actually playing.

A simple example program:
Quote
Psload "andi-music",10
For I=1 to Psbanklength(10)
Psplay 10,I
Wait 400
Next I
Psstop

EDIT - There was a stupid bug in my original attachment that prevented single file SID modules from loading.  Should have tested this first.  A fixed version is attached.
Title: Re: call playsid.library
Post by: Hungry Horace on May 31, 2013, 11:11:48 PM
Wow! James666 you are bringing a lot of cool new stuff to AMOS!

I had been working on a Horace Goes Skiing remake before, so I can now add the C64 music as an added bonus :)

Looking forward to trying this out :)

Oh... And thanks!
Title: Re: call playsid.library
Post by: james666 on June 01, 2013, 12:10:19 AM
I had been working on a Horace Goes Skiing remake before, so I can now add the C64 music as an added bonus :)

The only snag is that playsid.library is rather CPU-heavy.  I believe it's converting 6502 code on the fly as well as emulating the brilliant SID chip.