It is currently Mon May 20, 2019 8:16 am

All times are UTC - 7 hours



Forum rules





Post new topic Reply to topic  [ 10 posts ] 
Author Message
PostPosted: Wed May 08, 2019 5:47 pm 
Offline

Joined: Wed Apr 10, 2019 4:24 pm
Posts: 22
I'm trying to make my own SNES game. The next thing I wanted to add was music. I downloaded SNES GSS and made a song. I exported the .spc file and attempted to fit it into my game but according to this reply by calima, .spc files are NOT meant to be played!

I tried to do File > Export with SNES GSS, but then I get I/O error 123.... So not sure how to proceed from there.

Is there another way to turn .spc files into the appropriate code?

Also, once I have the sound code, how do I actually include it in the ROM? I literally can't find any source other than this wikibooks article, but that talks about using .spc files!

Suffice to say I'm very lost...


Top
 Profile  
 
PostPosted: Wed May 08, 2019 7:24 pm 
Offline
Site Admin
User avatar

Joined: Mon Sep 20, 2004 6:04 am
Posts: 3678
Location: Indianapolis
I can't help with GSS specifically, but I can say while there are some practical reasons that you wouldn't use .spc files in a game, there's also no show-stopping reason that you can't do it anyways.

.spc file is just a saved state of what's in the SPC's memory. the SPC chip has a tiny ROM with a loader that is used to get started, but after that you must supply your own code that communicates between the CPU and SPC. So if you're just loading an .spc file, the code in your CPU-side will need to be compatible with the SPC-side of the interface. If it's not, you'll be able to start the music playing, but you'll never be able to talk the SPC chip again (well, not until you reset the system). If you don't ever want to change songs or play sound effects, you can play pretty much any .spc file.

For practical reasons, when you want to change songs and instrument sets, you probably want to store and transfer just those parts of data, and not an entire dump of SPC RAM. These kind of transfers, like all other communication (beyond that IPL boot ROM), is done manually by the user for both CPUs involved.

Instead of hacking all that stuff up though, it's probably better to get GSS working as intended. Just saying though.


Top
 Profile  
 
PostPosted: Thu May 09, 2019 12:09 am 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 935
There are no tutorials I'm afraid. The only GSS documentation is the README included in the GSS zip. The asm is reasonably commented.


Top
 Profile  
 
PostPosted: Thu May 16, 2019 11:38 am 
Offline

Joined: Wed Apr 10, 2019 4:24 pm
Posts: 22
So I managed to get the exported files by using the command line instead of the GUI (as stated in the README).

I have a bunch of files but honest to God I have no idea what assembly functions I'm supposed to call and in what order... the comments say nothing about what to do unfortunately.

All the assembly is written in wla dx which I can port to ca65 I guess (though that's gonna be tedious). But also, sneslib.h has some C functions, and I'm not even sure how to compile and assemble it!

Has anyone worked with SNES GSS in depth before? I found a video online where a guy shows how to use SNES GSS and use an SPC player to get it to play on an emulator, but not how to actually include the music in a SNES game


Top
 Profile  
 
PostPosted: Fri May 17, 2019 6:26 pm 
Offline

Joined: Wed Jul 09, 2008 8:46 pm
Posts: 258
I don't use the editor itself due to a platform incompatibility, but I know of some source code that does use SNESGSS in their games:

Furry RPG (music only, still a WIP): https://github.com/Ramsis-SNES/furryrpg
Kung Fu Master (music only, still a WIP): https://github.com/AntiheroSoftware/sfc-Kung-Fu-Master
undisbeliever's Simon Says (SFX only, no music): https://github.com/undisbeliever/1gam-c ... simon_says

sneslib.h is used for C compilers (although I'm trying to remember which one... tcc-65816?). The code seems to be adapted for C-based compilers in the first place, as there are some routines only implemented in C, and not in ASM. Reminds me of code compiled with pvsneslib. Hmm...


Top
 Profile  
 
PostPosted: Sat May 18, 2019 1:55 am 
Offline
Site Admin
User avatar

Joined: Mon Sep 20, 2004 6:04 am
Posts: 3678
Location: Indianapolis
Yeah, looks like it's intended to be used in C, the C functions call those assembly subroutines. So what you'll need to do if you're changing it to CA65, is port the assembly parts (the parts you need) to CA65, then recreate the C functions that you need in assembly.

I was originally looking at the copy of it someone put on Github. I decided to look at the version on Shiru's site, and in the /src/ folder there is another readme.txt, which is entirely missing from the Github version. Gee, that's totally not going to cause problems for people who try to use it.. WTF.

So here's the relevant excerpt from it:

Code:
Export and use

When all music and sound effects created, the project can be exported
(File>Export) for further use in a SNES program. The editor exports
a number of files:

spc700.bin -  contains compiled SPC700 driver code, samples, sound effects
              data. This means you don't need to use a SPC700 assembler.

music_N.bin - contains music data. Each sub song that is not marked as a
              sound effect will be exported into separate file. This allows
           to save room for more sample data, while music data is only
           loaded when needed.

sounds.asm  - contains incbin's in the WLA DX format, considering LoROM
              configuration.

sounds.h    - contains automatically generated aliases for every sub song
              and sound effect, as well as sub song names.

The latter two files aren't necessary, they meant to be used in a specific
SNES dev environment. The interfacing part of the environment is provided
along with the editor in the /snes/ directory, it consist of two files,
sneslib.asm and sneslib.h. There are 65816 assembly functions to load the
SPC700 driver and communicate with it, as well as C interface to these
functions.

You can either adapt provided code for your purposes, or create a new one,
using the code as a guide. spc700.bin loading and starting address is
$0200. When the driver is loaded, communication is done through APU ports
using the communication routines (see snes/sneslib.asm:542 and beyond).
Driver loading code is in snes/sneslib.h:774. 'Play a sound effect'
function is in sneslib.asm:842, it also uses spc_command_asm routine
(uniform for most commands), which is in sneslib.asm:658.

The spc700.asm file in the /snes/ directory is only provided for reference,
in case you're interested in internals of the driver. It does not need to
be compiled or otherwise used in a SNES program.

Take a note that, unlike the editor or exported SPC file, driver starts in
mono mode, for compatibility reasons, as many old TV sets does not have
stereo, and some part of the sound would be missing. To get stereo output,
the stereo enable command must be sent first.


Top
 Profile  
 
PostPosted: Sat May 18, 2019 7:11 pm 
Offline

Joined: Wed Apr 10, 2019 4:24 pm
Posts: 22
So I'm looking at the sneslib.asm file to see what all I can use. It has a lot of PPU related functions that I'm gonna ignore. Also, I'm not gonna bother with the .h file because I really don't wanna open a can of worms of getting C code to work lol.

Anyways one handy subroutine is this guy:

Code:
;void spc_load_data(unsigned int adr,unsigned int size,const unsigned char *src)

spc_load_data:
    ...                 ; do a bunch of stuff
    rtl


I had found this guide earlier on how to transfer data to the APU, and this seems to follow that guide more or less.

So with that subroutine I can transfer spc700.bin (the driver) to APU at address $0200. Nice.

There's also another subroutine:

Code:
;void spc_stereo(unsigned int stereo);

spc_stereo:
    ...                 ; do a bunch of stuff
    rtl


I can use that guy to enable stereo. Also nice.

Now here's the part I'm confused about. First, what do I do with my music data, music_1.bin. The README.txt does not mention where in the address space it's supposed to go. I looked at the stop of the driver file, spc700.asm, and saw this:

Code:
//memory layout
// $0000..$00ef direct page, all driver variables are there
// $00f0..$00ff DSP registers
// $0100..$01ff stack page
// $0200..$nnnn driver code
//        $xx00 sample directory
//        $nnnn adsr data list
//        $nnnn sound effects data
//        $nnnn music data
//        $nnnn BRR streamer buffer


I'm not sure how to read that... Is it saying that the music data should go right after the driver data? I.e. $0200 + sizeof(spc700.bin)?

Another thing is I have no idea how to tell the music to start playing. Here are all the subroutines (at least the ones related to the APU) given by sneslib.asm
    1. spc_load_data
    2. spc_command_asm (sends a command. Appears to get the parameters from global variables acting as "mailboxes")
    3. spc_command (also sends a command but gets paramsters from the stack. I guess this is for C compatibility)
    4. spc_stereo
    5. spc_global_volume
    6. spc_channel_volume
    7. music_stop
    8. music_pause
    9. sound_stop_all
    10. sfx_play
    11. spc_stream_update

There does not appear to be a music_play command. Overall I'm very lost as to what's going on...


Top
 Profile  
 
PostPosted: Sat May 18, 2019 7:23 pm 
Offline

Joined: Wed Apr 10, 2019 4:24 pm
Posts: 22
UPDATE

Ah dammit... I just looked in sneslib.h. I thought that file was just there to give hooks for C code to call the assembly routine.

NOPE

There is vital C code in that header...

For one:

Code:
/*initialize sound, set variables, and upload driver code*/

void spc_init(void)
{
    const unsigned int header_size=2;
    static unsigned int i,size;

    size=spc700_code_1[0]+(spc700_code_1[1]<<8);

    spc_music_load_adr=spc700_code_1[14]+(spc700_code_1[15]<<8);

    spc_stream_enable=FALSE;

    nmi_enable(FALSE);

    if(size<32768-header_size)
    {
        spc_load_data(0x0200,size,spc700_code_1+header_size);
    }
    else
    {
        spc_load_data(0x0200,32768-header_size,spc700_code_1+header_size);
        spc_command(SCMD_LOAD,0);
        spc_load_data(0x0200+32768-header_size,size-(32768-header_size),spc700_code_2);
    }

    spc_command(SCMD_INITIALIZE,0);

    nmi_enable(TRUE);
    nmi_wait();
}


So turns out there is a LOT that you have to do to initialize the APU. Loading the spc700.bin driver file into $0200 is NOT sufficient; I need to call spc_init(). Boy that seems like something the README should say...

Furthermore, there exists exactly the function I want:

Code:
/*play music*/

void music_play(const unsigned char *data)
{
    static unsigned int size;

    size=data[0]+(data[1]<<8);

    spc_command(SCMD_MUSIC_STOP,0);
    spc_command(SCMD_LOAD,0);
    spc_load_data(spc_music_load_adr,size,data+2);
    spc_command(SCMD_MUSIC_PLAY,0);
}


Even though the comment elucidates nothing, I can tell from context that data should be a pointer to music_1.bin. So if I pass that in, I should be golden.


Actual questions

How do include a C header file into an assembly program? Do I just use .include?

How do I get it to compile? I'm using ca65 as my assembler. Do I need like a C compiler or something?

Also, how specifically do you call C functions? I know you put arguments on the stack and do a jsl, but what all needs to go on the stack and in what order?


Update

I forgot to consider the possibility that I could port the C functions to assembly equivalents. They don't look so complex (they stand on the shoulders of the existing subroutines after all).


Top
 Profile  
 
PostPosted: Sun May 19, 2019 12:02 am 
Offline
Site Admin
User avatar

Joined: Mon Sep 20, 2004 6:04 am
Posts: 3678
Location: Indianapolis
rchoudhary wrote:
How do include a C header file into an assembly program? Do I just use .include?

How do I get it to compile? I'm using ca65 as my assembler. Do I need like a C compiler or something?

Also, how specifically do you call C functions? I know you put arguments on the stack and do a jsl, but what all needs to go on the stack and in what order?



cc65 (included with ca65) is the C compiler that produces ca65-compatible output. With cc65 I have very little experience with including asm in a C program, and no experience including C in an asm program. You can't .include the H file, the assembler won't recognize C syntax. I think what you're supposed to do, is in the assembly file .import global variables and C function names. You would compile the C file (er, H file in this case I guess), assemble the ASM file, then using LD65, link the object files together. At the linking stage, the .imported label names will be reconciled.

That being said, if you're writing the game in 100% asm anyways, and because there's very little C code in this case, I think it would be easier to just manually rewrite that C code into assembly. I might be overestimating the difficulty of calling C routines from assembly because I've never tried it. Someone else hopefully can answer the 3rd question (I'm curious too). With cc65 though I do know it outputs 6502, not 65C816.

edit: you figured it out before I finished the post :)


Top
 Profile  
 
PostPosted: Sun May 19, 2019 12:36 am 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 935
I don't know what the tcc-816 ABI is. cc65 ABI is well documented, but this code is for tcc-816.
https://github.com/cc65/wiki/wiki/Param ... onventions

I agree that for OP's project it's best to write the init and music_play funcs in asm.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group