Author Topic: Messing with Libdragon  (Read 12043 times)

0 Members and 1 Guest are viewing this topic.

Offline jonesalmighty

  • Full Member
  • ***
  • Posts: 135
  • Karma: +11/-0
    • View Profile
    • GitHub
Re: Messing with Libdragon
« Reply #15 on: December 23, 2016, 12:57 AM »
It now compiles correctly but for some reason it is only registering the "no sound" driver, which obviously means that no sound is output... judging by the framerate drop, apart from that I think it is working correctly...

Hopefully I will be able to figure out why this is happening but it might take a while!

Edit: I think it must be a problem with the makefile but I am having trouble figuring out why it is only making drv_nos.o even though I am expecting a number of other drivers to be made... especially drv_n64 which is declared! however I am now seeing double after one too many beers so will have to give up (probably until after Christmas!) but if you @saturnu, @krikzz, @chillywilly can see anything wrong, please shout... I think this is beneficial for the whole homebrew community, especially if I can get it integrated with the main CVS (why they are not on GitHub I cant understand...)

so close yet so far!

« Last Edit: December 23, 2016, 01:24 PM by jonesalmighty »
Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth...

Offline jonesalmighty

  • Full Member
  • ***
  • Posts: 135
  • Karma: +11/-0
    • View Profile
    • GitHub
Re: Messing with Libdragon
« Reply #16 on: December 23, 2016, 01:25 PM »
Everything now works! I missed a couple of += in the make file  :-[ .   Again, files can be found at https://github.com/networkfusion/libmikmod , build and install from  the N64 sub directory...
Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth...

Offline ConkerGuru

  • Newbie
  • *
  • Posts: 46
  • Karma: +3/-0
    • View Profile
Re: Messing with Libdragon
« Reply #17 on: December 23, 2016, 02:12 PM »
Compiled the library again, and from my tests I can verify that sound playback works again. Thanks for taking the time to bring the MikMod library for N64 more up to date, I'm sure the many of us will appreciate the various fixes the 3.3.10 version will bring!

Also a bit unrelated, but I read up on the available documentation for Libdragon concerning the DragonFS filesystem: https://dragonminded.com/n64dev/libdragon/doxygen/group__dfs.html#_details

The details mention that DFS files have a maximum size of 16,777,216 bytes, which I think would put it at around 16MB. I'm not sure what exactly this means. Does it mean that files included have a maximum limit of 16 MB, or does it apply to the filesystem itself?

Offline ConkerGuru

  • Newbie
  • *
  • Posts: 46
  • Karma: +3/-0
    • View Profile
Re: Messing with Libdragon
« Reply #18 on: December 23, 2016, 06:46 PM »
Seems like there's yet another problem. I don't think this has anything with the updated library to do, as this issue has probably been around for years, but I'll bring it up anyway; apparantly there's a place in RDRAM (about 0x4B0 bytes in size) where two 32-bit values are being written each time a sound is played(both values increment after each step). After a certain amount of those values have been written sounds simply won't play anymore until the values are nulled with a RAM editor(like Cheat Engine for example). I'll try to demonstrate it better with pics:

The first image shows the area in RDRAM, the 0x00000005 is where this "sound last played counter" starts.


The last image shows where it stops at(it's basically at offset 0x4AF), and this is where the problem occurs.

Gotta wonder why it was necessary to store two values each time a sound is played, since it limits the number of sounds that can be played(to clarify, this issue is present even in the dfsdemo example). This shouldn't really be happening. I wonder if this range has to be manually nullified somehow...
« Last Edit: December 23, 2016, 06:49 PM by ConkerGuru »

Offline jonesalmighty

  • Full Member
  • ***
  • Posts: 135
  • Karma: +11/-0
    • View Profile
    • GitHub
Re: Messing with Libdragon
« Reply #19 on: December 23, 2016, 09:44 PM »
That is beyond me I am afraid. Perhaps there are 2 values because it is stereo? anyway, it might be worth sticking an issue on libdragon's GitHub page https://github.com/DragonMinded/libdragon/issues as it is more likely you will get help there than here...

Also, are you using a clone of the latest master which has changed some audio related stuff?
« Last Edit: December 23, 2016, 09:52 PM by jonesalmighty »
Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth...

Offline ConkerGuru

  • Newbie
  • *
  • Posts: 46
  • Karma: +3/-0
    • View Profile
Re: Messing with Libdragon
« Reply #20 on: December 23, 2016, 10:06 PM »
I'm using a version of Libdragon that was pre-installed on the Ubuntu VM. I think the installation is a few years old by now(from around 2012 I believe if going by the last modified dates). Might as well try the latest master before sticking up a issue, chances are the issue has since been resolved.

Edit: I had some trouble with installing the new files required for compiling the updated libdragon files(a couple mips-elf-gcc files were somehow missing from the bin folder of mips64-elf), so I went back to the old mips64-elf-gcc 4.4.0 installation and simply copied over the new source files to the main libdragon folder, and my project compiled just fine. The issue mentioned in my previous post still persist though.

I'll mess around a bit with the libdragon source and see if I can find anything that writes those values. Maybe I find something in there, maybe not, but I guess it's worth a shot.

I also got the timer system working in MESS by using a fixed timer.c file by Chilly Willy, so now I can finally see the sprite being animated. The animation kinda works, but frames are still not displayed in the right order. I'll try messing some more with the code responsible for displaying the frames and see if I can get it fixed.
« Last Edit: December 24, 2016, 09:40 PM by ConkerGuru »

Offline jonesalmighty

  • Full Member
  • ***
  • Posts: 135
  • Karma: +11/-0
    • View Profile
    • GitHub
Re: Messing with Libdragon
« Reply #21 on: December 26, 2016, 09:33 PM »
I just wanted to say that with the latest libdragon and libmikmod I am also seeing the same symptoms (although haven't used a memory debugger to check)...
Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth...

Offline ConkerGuru

  • Newbie
  • *
  • Posts: 46
  • Karma: +3/-0
    • View Profile
Re: Messing with Libdragon
« Reply #22 on: December 26, 2016, 10:32 PM »
Yeah, it's such a pity that this sort of thing has to be around. Could either be due to the way the audio library of Libdragon was coded, or maybe it's something internal to LibMikMod.

I've just begun traversing through the source code of both Libdragon and LibMikMod to see if I can find the culprit. Haven't found the line of code responsible for writing those values. If found however, then it could be possible to rewrite the code so it doesn't write them to RAM in such a horrible way(like in the pics I posted earlier), or maybe remove it altogether. I'm not so confident about the latter choice, since removing the function could likely lead to the program crashing if not careful.

As for the progress on my little homebrew project, it has been going along nicely so far. I had to write my own code for animating the sprite that should be moving about on the screen, since the one from the spritemap example proved to be useless to me. I also made a video showcasing the homebrew. I didn't know what username you prefer to be referred to as, but I went with "jonesalmighty" if that's alright with you: https://www.youtube.com/watch?v=Z8qb7Q3Y-y8

I have yet to test it on real hardware. If it runs just as fine like it does in MESS, then I think it is pretty much complete. What's also left is to fix the issue with sounds not being able to play after a number of times, and to comment some new sections of the code. The latter I think I can take care of though.

Edit: I tested my homebrew on hardware, and it ran a bit sluggish when playing a sound file(how much the framerate lagged depended on the size of the sound byte). Luckily I found out the reason; it was the way I drew the background that caused the homebrew to lag. However, now I have to find a way to draw it to the screen via hardware to see if lag can be reduced that way. Would mean splitting the image into two pieces. I'll see to it later on how to deal with that.
« Last Edit: December 27, 2016, 12:05 AM by ConkerGuru »

Offline ConkerGuru

  • Newbie
  • *
  • Posts: 46
  • Karma: +3/-0
    • View Profile
Re: Messing with Libdragon
« Reply #23 on: December 27, 2016, 02:03 PM »
I managed to draw a textured rectangle that fills the whole screen. Had to convert all the .sprite files to 16 BPP format so the background display properly(and not hang on Cen64. Have yet to test this on hardware, but I suppose it should cope just fine):



Only bad thing is that when mirroring is enabled, the texture is also mirrored vertically. In my case I don't want it to happen, especially when drawing a simple background that is supposed to tile across the screen. Maybe the rdp code of Libdragon could be changed so the texture aren't vertically mirrored. I'll try looking into it as well when I can figure out which line of code does what.

Edit: Got it sorted out now. All I had to change was this line in rdp.c:
Code: [Select]
__rdp_ringbuffer_queue( ((texslot & 0x7) << 24) | (mirror_enabled == MIRROR_ENABLED ? 0x40100 : 0) | (hbits << 14 ) | (wbits << 4) );to:
Code: [Select]
__rdp_ringbuffer_queue( ((texslot & 0x7) << 24) | (mirror_enabled == MIRROR_ENABLED ? 0x10100 : 0) | (hbits << 14 ) | (wbits << 4) );Me thinks it's time to implement different types of texture mirroring, like "MIRROR_HORIZONTAL", "MIRROR_VERTICAL", and so on to allow for more free choice.

Now, to get myself to convert the soundtest sprite to 16 BPP as well. After that's done, I will resume studying the Libdragon code to find areas where further improvements could be performed.

Edit: So, I've tested the new ROM on my everdrive, and thankfully the lag seems to be gone. Drawing 32 BPP sprites sure is slower than drawing 16 BPP ones I suppose. Using a 32x64 size texture tiled across the screen also seemed to help with console performance(though on MESS the ROM now runs twice as fast. Sound still plays at normal speed on that emulator though despite this.) I also updated the testproj.zip again with the latest source, along with modified libdragon source files that makes some things in my homebrew work as intended.
« Last Edit: December 28, 2016, 01:44 AM by ConkerGuru »

Offline ConkerGuru

  • Newbie
  • *
  • Posts: 46
  • Karma: +3/-0
    • View Profile
Re: Messing with Libdragon
« Reply #24 on: December 28, 2016, 03:17 PM »
Been doing some messing around with pre-loading sounds before hand to see if it would eliminate the pausing of the program(because the sound data has to finish being copied to RAM), and it seems to work. For a sound test this doesn't matter much, but for an actual game then it does matter, because the flow of the game would be severely affected if a sound always had to be copied before it can be played back by the N64.

One thing I have to keep in mind though is to only pre-load the sounds required and free them once they're no longer needed. This info is only for actual game development though, but maybe it could be a good thing to know for future reference.

Anyway, I now know what those increasing numbers are representing; they represent the sound files that were loaded into memory. Only thing that stumps me though is why they aren't being cleared when a sound resource has been freed...
« Last Edit: December 28, 2016, 03:19 PM by ConkerGuru »

Offline jonesalmighty

  • Full Member
  • ***
  • Posts: 135
  • Karma: +11/-0
    • View Profile
    • GitHub
Re: Messing with Libdragon
« Reply #25 on: December 28, 2016, 07:23 PM »
I have also been playing around with sound...

Here is my latest code:

Code: [Select]
#include <mikmod.h>
#include <libdragon.h> //needed for audio_get_frequency()
#include "hashtable.h"

MODULE *moduleBGM = NULL;

/* sound effects */
hashtable* samples = NULL;

/* voices */
SBYTE voiceSFX;

void sndInit(void)
{
    samples = hashtable_create();

    /* register all the drivers */
    MikMod_RegisterDriver(&drv_n64);
    MikMod_RegisterAllLoaders();

    /* initialize the library */
    md_mode = 0;
    md_mode |= DMODE_16BITS;
    md_mode |= DMODE_SOFT_MUSIC;
    md_mode |= DMODE_SOFT_SNDFX;
    md_mode |= DMODE_INTERP;

    md_mixfreq = audio_get_frequency();

    MikMod_Init("");

    /* reserve 2 voices for sound effects */
    MikMod_SetNumVoices(-1, 2);

    /* get ready to play */
    MikMod_EnableOutput();

   
}

void sndPlayBGM(char* filename)
{
    if (Player_Active())
    {
        Player_Stop();
    }
    Player_Free(moduleBGM);
    moduleBGM = NULL;

    moduleBGM = Player_Load(filename, 64, 0);

    if (moduleBGM)
    {
        Player_Start(moduleBGM);
        Player_SetVolume(20);
    }
}

void sndStopAll(void)
{
    Voice_Stop(voiceSFX);
    Player_Stop();
    MikMod_DisableOutput();

    int index = 0;
while (index < samples->capacity) {
        Sample_Free(samples->body[index].value);
        index = index + 1;
}

    hashtable_destroy(samples);

    Player_Free(moduleBGM);
    moduleBGM = NULL;

    samples = hashtable_create();
    //MikMod_Exit(); //I dont think we should ever exit as that would mean reinitialising?!
}

void sndPlaySFX(char* filename)
{
    if (!Voice_Stopped(voiceSFX))
    {
        Voice_Stop(voiceSFX);
    }
       

    if (hashtable_get(samples, filename) == NULL)
    {
        hashtable_set(samples, filename, Sample_Load(filename));
    }

    voiceSFX = Sample_Play(hashtable_get(samples, filename), 0, 0);
    Voice_SetVolume(voiceSFX, 200);
}

void sndUpdate(void)
{
    if (moduleBGM)
    {
        if (Player_Active() || !Voice_Stopped(voiceSFX))
        {
            MikMod_Update();

        }
    }
}

It relies on hashtable.h found here: https://github.com/marekweb/datastructs-c for only loading samples once as they are first used.

this code is working really well as far as I can see but you would need to check if there is any memory leaks when stopping and restarting sound...
Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth...

Offline ConkerGuru

  • Newbie
  • *
  • Posts: 46
  • Karma: +3/-0
    • View Profile
Re: Messing with Libdragon
« Reply #26 on: December 29, 2016, 04:23 PM »
Sorry for not replying earlier. I tried the new sound code on my test homebrew, but somehow it always fails to compile with the hashtable stuff in it(I did include "hashtable.h" in my project source, so I don't know what's going wrong or what I'm doing wrong). Think I better copy the project directory, strip out all the unneeded stuff and leave just the sound code and resources, and try to test it there instead of fiddling with the source to my other homebrew all the time.

Anyway, after some studying with a hex editor I found out and assume it must be some code in the system.c file of Libdragon that doesn't bother zeroing out the region with all the values after all the neccessary files have been loaded. The values aren't really needed anymore once the files are loaded into memory, so why this sort of region isn't nulled is entirely beyond me(as well as anyone else probably).

Do note that this is just pure assumption from my side(coupled with the limited knowledge I have about Libdragon's internals), so these facts could as well turn out to be just completely wrong.

I haven't dared fiddling with the code in the system.c file, but I guess it wouldn't hurt to get my hands dirty with the Libdragon source and try to fix things here and there. If all else fails however, I might as well sign up on github and stick an issue on the Libdragon Github page and see if I can get more help on there, because these problems are starting to drive me nuts and I'm running out of ideas or ways to deal with them.

Edit: Just installed a newer version of Ubuntu in vmware, which I hope will allow for all the required files to properly install (especially all the mips-elf- related ones). I'll wait a bit for the update to altra64 before I'll do anything else though. Once I get everything installed I will be moving all my project files from the old ubuntu image to the new one.
« Last Edit: December 29, 2016, 06:31 PM by ConkerGuru »

Offline jonesalmighty

  • Full Member
  • ***
  • Posts: 135
  • Karma: +11/-0
    • View Profile
    • GitHub
Re: Messing with Libdragon
« Reply #27 on: December 29, 2016, 05:09 PM »
I am just about to integrate the sound stuff into https://github.com/networkfusion/altra64

You may also be interested in the make file and build scripts (as they add the object files automatically, which I guess is your problem with the hashtable header)

I will post when it is done (shouldn't take very long!)
Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth...

Offline jonesalmighty

  • Full Member
  • ***
  • Posts: 135
  • Karma: +11/-0
    • View Profile
    • GitHub
Re: Messing with Libdragon
« Reply #28 on: December 29, 2016, 07:14 PM »
Okay,

I have now done a check-in with the updated sound bits...

I have also managed to work out why background audio needed to be enabled to play voices... it turns out that voice isn't reported as playing until a MikMod_Update(); has been performed so was always bypassing if (!voice_stopped... Adding a single MikMod_Update(); in the play sfx function cured this!
Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth...

Offline ConkerGuru

  • Newbie
  • *
  • Posts: 46
  • Karma: +3/-0
    • View Profile
Re: Messing with Libdragon
« Reply #29 on: January 01, 2017, 01:00 PM »
Just wanted to say that after a couple days I've finally managed to install the MIPS toolchain and the neccessary files. I had to manually install some things like libgmp-dev and so on even though the linux script was supposed to automate those tasks. All is well now though.

Only problem I'm having is installing libmad-n64. It is primarily needed for compiling altra64 as far as I can understand. I typed ./configure within the terminal in the folder libmad is located, and it generated a Makefile. Typing "make" threw up an error saying that fforce-mem is unrecognized. Removing that command from the makefile generated all the needed files, all except libmad.a. Screw all that, I now know that libmad.a has been generated. however, upon typing "sudo make install" the files were being installed into the wrong folders! Guess I have to modify the install paths in the makefile to make sure they're being put in their correct locations. After that I'll try to resume compiling altra64.

Apart from that, everything else seems to be fine. I'm able to compile my own stuff without problem. Only thing I don't like with GCC 5.1.0 is that a small block of asm code is being split from the rest of the code and mixed in with the data after the ROM has been compiled, and I personally don't find that very tidy. Just a small nitpick of mine, and I guess it doesn't affect functionality in any way.

Edit: tried compiling altra64 again, and now it complains about yaml.h not being found. I'll try mess some more to see if I can get libyaml installed.
« Last Edit: January 01, 2017, 01:24 PM by ConkerGuru »