Next Page

USF player library by haspor at 5:36 PM EDT on October 2, 2013
I'm looking for a library to play USF/MINIUSF files on Unix/Linux. Anyone know a proper candidate for it? It would be for an Android application i'm developing (free app).
by kode54 at 11:43 AM EDT on October 15, 2013
USF is unlikely to be playable on ARM, as the existing USF player/emulator library, lazyusf, makes extensive use of x86 32 bit recompilation for both R4300i and RSP emulation. Each core's C interpreter version is an order of magnitude of four times as slow as its recompiling version, making a full recompiler 16 times as slow on x86.

Under my own testing, the full interpreter mode barely pulls real time on my old Athlon 64 3200+ machine. Just imagine how slow that will be running on ARM.
by haspor at 12:15 PM EDT on October 15, 2013
i see, damnit, i guess there is no way to play it on Android then.
by kode54 at 4:03 PM EDT on October 15, 2013
You can always try, but there's no guarantee that it will work properly.

The emulator loops could probably use some major idle detection to improve their playback speed.

Still, you have to remember, N64 games rendered their music in software using the processors available. The RSP did support vectorized math (add/subtract/multiply/divide/etc operations on four floating point numbers in a single opcode) which the recompiler turns into SSE math opcodes. You'd have to look into converting that to something that will work on Android platforms.

Probably not going to happen, no.
by haspor at 7:47 AM EDT on October 20, 2013


edited 7:49 AM EDT October 20, 2013
by kode54 at 7:48 PM EST on February 14, 2014
I have my own lazyusf fork now, here:

https://bitbucket.org/kode54/lazyusf

It has been stripped of all processor specific code, except for the new RSP, which contains optional SSE2 or SSSE3 code.

In its current form, the Makefile is specific to Mac OS X / Clang, but relevant code could be changed fairly easily.

It works as a piped process which you can call with popen/fread/fwrite. Upon opening, it will look for the following data on stdin:

uint32_t enable_compare;
uint32_t enable_fifo_full;

Then it looks for repeating patterns of:

uint32_t reserved_section_size;
uint8_t reserved_section[reserved_section_size];

That repeats until reserved_section_size is 0.

Then it immediately loads the ROM and state into the emulator core, starts executing, then proceeds through this exchange:

W uint32_t sample_rate;
W uint32_t sample_count;
W int16_t samples[sample_count];
R uint32_t keep_running;

And it keeps running until keep_running reads back 0, or fails to read back at all, signaling a pipe breakage.

I may opt to move all the state into a portable structure so that it can be dynamically or statically linked, but that will require quite some work.

Also, it may yet be too slow for your needs, especially on a small scale ARM or MIPS CPU.
by haspor at 8:44 PM EST on February 14, 2014
WOW, excellent job :)

Does it demand more from CPU than Highly Theoretical lib? If yes, then i rather wait, HT lib caused some problems with certain devices earlier.
by kode54 at 8:00 PM EST on February 15, 2014
The API is quite simple. You couple it with a PSF loader, such as my psflib C library.

Basically, with psflib, you draft up file a file access system. I advise looking in here, specifically the parts involving usf_loader_state.

You would use psf_load with no loader functions, or possibly just the tag loader function for metadata, and a type of 0, and it will return either -1 on failure, or the type of the PSF requested. When you wish to load a specific PSF type, I suggest passing that type to the function so it verifies the types of all files opened.

You instantiate the loader state structure, and assign a newly allocated usf emulator library to it, and call the psf_load with both the loader and loader metadata callbacks. The loader uploads the reserved sections to the emulator in the correct order, and the info function retrieves the two supported emulation behavior override tags and sets the correct members of the loader structure.

Once loading has completed properly, you use those two tag property variables in the structure to call two setter functions on the lazyusf instance.

Then you call usf_render to produce actual sample data, and optionally retrieve the last DAC sample rate. If your player needs to know the sample rate at startup, it's safe to call this function once, store the sample rate, and save the first block of samples for later. With many USF sets, loading the emulator up and calling for a single block of samples is quite rapid. For a number of others, like Animal Forest or Neon Genesis Evangelion, it's a bit slow, so maybe advisable to only bother when starting playback.

Before disposing of the allocated memory block, you need to call usf_shutdown on it, to free the mmap'd block of memory used by the emulator core.

I would like to try to make it so that all memory is allocated against the initial state structure, but alas, that doesn't seem as easy as I thought. When I tried this, certain structures would overlap other parts of the structure.

I also use an offset at the head of the base memory block, initialized by usf_clear, which automatically aligns the internal lazyusf state structure on a page boundary. Paragraph alignment is all it really needs, for the RSP register and temporary structures, for aligned access by SSE2 opcodes, if you enable them on x86/x86_64 platforms. It may help a bit with auto vectorization on non-x86 platforms, though.

As with the stock Iconoclast RSP, defining ARCH_MIN_SSE2 for just rsp.c will enable use of SSE2 intrinsic functions, while defining ARCH_MIN_SSSE3 will use both. Do not use both preprocessor definitions at once, because there are several places in the code in which the SSE2 macro takes precedence over the SSSE3 macro. Neither apply to non-x86 architectures, unless there's some compiler which can produce ARM or MIPS compatible SIMD code from Intel intrinsic functions.

EDIT: I chose to use reserved upload function, like Neill's libraries, instead of bundling PSF loading into every player. Since PSF parsing is so simple, I figured a simple loader library would benefit any PSF player. Check out that linked Obj-C++ source code for examples of loading every xSF format currently in existence, and within my Github or Bitbucket accounts, all of the libraries necessary to interface as the player cores for those formats.

edited 8:05 PM EST February 15, 2014

Okay, the API is in usf.h. usf_internal.h is the internal structure required by the entire library, which I didn't see fit to split up into components because I am lazy.

All of the public functions in usf.h are fairly self-explanatory, except for the upload function's return value. It's like most POSIX library functions, returning -1 on error and 0 on success. The only case where it really fails is either if it can't allocate the memory, or if the data is invalid.

Hmm, I need to add more error checking, since the AllocateMemory internal function from the original code can return error states on failure.

It also needs some better means of allocating the majority of the core memory, since it uses mmap, and would probably need a generic memory allocation and mapping function set so it can be reused on Windows, for instance. Something based on VirtualAlloc/VirtualFree, like the original Win32 code it's based on.

edited 8:15 PM EST February 15, 2014
by haspor at 3:03 AM EST on February 16, 2014
awesome, this will be my next adventure right after UADE update :)
by kode54 at 8:23 PM EST on February 18, 2014
I suggest you pull my latest version as-is and not try to make any further modifications. If you still need any modifications, let me know.

I've eliminated all of the internal headers from the public interface header. That should fix all odd warnings or errors importing it into other projects.

As for missing usf_state_t in any C file, that should not happen. If it does happen, it means that particular C file is missing an include reference for usf_internal.h below all of its other imports.

Next Page
Go to Page 0 1 2 3

Search this thread

Show all threads

Reply to this thread:

User Name Tags:

bold: [b]bold[/b]
italics: [i]italics[/i]
emphasis: [em]emphasis[/em]
underline: [u]underline[/u]
small: [small]small[/small]
Link: [url=http://www.google.com]Link[/url]

[img=https://www.hcs64.com/images/mm1.png]
Password
Subject
Message

HCS Forum Index
Halley's Comet Software
forum source