OpenSPC v.300Linux (based on Lite/Direct To Disk version) Linux port and general code tweaking by Chris Timmerberg (ctimmerb@usa.net) Hi! Here's the long-awaited port of OpenSPC to linux. I say linux, primarily because that's all I'm able to test it with (at least presently). If your platform is relatively portable and has a /dev/dsp it may very well work there as well. It may even work with code that pretends to be /dev/dsp, such as I've seen for Os/2. This is completely speculation, I've never tried it. Even in the lack of /dev/dsp, you should still be able to compile it almost everywhere there's a gcc or other standard compiler. This will give you full wav/it dumping facilities, as well as the ability to pipe stdout into another player app which handles wav-like data. I've found splay to work fine. Again, I havent tested others. Feel free to do so yourself. The tty files were copied from another project and as such contain alot of extra stuff #ifdef'ed which linux doesnt use. I can't say whether or not these other code blocks work on their respective platforms, sorry. The binary I send along was built on my 486 running Stampede. It uses no extra libraries beyond Glibc 2.1. Everyone should have this by now. If you dont, feel free to compile your own copy (of the OpenSPC, or of glibc). PGCC 1.1.3 was used. The makefile includes -O6 -mpentium optimization levels by default. This seems to generate the best quality code for most people's systems. And no, mpentium DOESNT seem to harm a 486 any. My 486 is doing just lovely playing back the spc's I've tried. I always use at least these options when compiling everything (occasionally a couple extras in addition). The overall behavior of this port is somewhat different from the original. Assuming one has enough cpu power (it shouldnt be hard to, my 486 did it) you can dump to several destinations at the same time. This includes wav file, IT file, stdout, and soundcard. The program code sets all output variables to 0. Options you specify for -w -i -p and -l then turn on any of the 4. If none was specified it turns on wav. Each enabled option is then checked for success and if necessary turned off. If no output options remain it finally gives up, and exits. Data is written directly to /dev/dsp. The original code made no attempt to buffer writes, and I didn't make any modifications in that area. As far as I can tell, /dev/dsp and/or the soundcard itself have at least a small buffer. This is probably not sufficient to prevent breakups if you're doing something cpu-intense. A buffer may be added eventually... Several command line options were added: -l enables the audio card output code. As many sound cards do not possess an exact frequency match, the audio output is by default tweaked to match what your soundcard reports it was set to. This does not SEEM TO affect it output, but does affect wav. If your card's status report was in error or your goal was to dump an exact frequency wav you may disable the adjustment with the -a option. -p enables piping support. This data is identical to that which is fed to a wav file or /dev/dsp. You may send this directly to an audio player of your choice. The -P option to accept input from stdin is wishful thinking for a next version. It'd be nice to be able to zcat, bzcat, or unzip -c compressed spc file(s) into this player, and beats trying to write support code for handling different compression methods. Aside from everything mentioned above, the base code remains for the most part, unchanged. I include the two text files from the original dos version, renamed to openspc.dos.txt and source.dos.txt. The next version may also include as well as the mentioned earlier buffering system and input pipes, the ability to batch play multiple files, general code cleanup and optimization, and maybe some other sound file formats... Candidates for other formats include gym, cym, nsf, and anything else that isnt supported by other linux players. Within reason, and as long as my 486 handles it reliably. :) If you want a netscape plugin, write it yourself. I dont do netscape plugins. (Netscape is piggish enough on a 486 without having MORE overhead, thank you very much!!) Meanwhile this existing program SHOULD work as a 'helper app' type thingy. No I didnt test that either. Misc note: This program uses <__math.h> for the pow2 and __log2 functions. These functions generate inline assembly code, which is both shorter and faster than calling external library functions from linking with the -lm option. Using code from the NORMAL header I've determined to require an alternate sequence of: #define __USE_EXTERN_INLINES 1 #define __USE_ISOC9X 1 #include This also changes the function names required, to log2f and __pow2 Oddly enough, the code generated by this contains many more instructions of overhead. <__math.h> generates a warning about __log1p which I dont even use. This warning seems to be due to a bad header file, not my code. The warning is harmless and may be ignored. The other warnings are going to be cleaned up eventually. Release notes for version .201Linux: * Overlooked changing a few instances of 'dump' into 'itout'. This caused IT dumping to generate incomplete files. * WAV dumping no longer generates any temp files * Upgraded from PGCC 1.1.1 to 1.1.3, and threw in -ffast-math in compilation options. * Accidentally packed 'source.dos.txt' into the archive twice the first time around. Only need ONE copy of this :) Release notes for version .300Linux: * Downloaded dos version .300 and re-implemented all my changes including stripping _ symbols in .S files, #including <__math.h> in sound.c, and tons of stuff in lite.c * lite.c now features a shutdown function for orderly shutting down. * lite.c has two extra \r characters by popular demand :) * Patched spcmain.S to not use self-modifying code in SPC_READ_RAM_ROM Release notes for version .301Linux: * Features migrated from the .301 dos version finally - id666 tags and new spc core. The id tags allow the player to know how long to play a particular file for. * The code from the dos version's lite.c was WRONG WRONG WRONG and generated really silly play times. So I fixed that and changed it to read the whole id tag header into a 'struct' all in one read. * The code for -t was also slightly incorrect in the dos version and my previous release. We now handle all three cases: seconds only with and without a leading colon, as well as the previous minutes:seconds case. Also properly handles stuff like 90 or :90 or 0:90 (or even 1:90)... * spcmain.S from the dos version included more silly self-modifying code in .301. When will they learn??? .... fixed * Dos version collided with my usage of the -l parameter. I kept mine, -l is still linuxout audio method, and a capitalized -T is used to disable the playback length mentioned in the idtag resulting in unlimited length playbacks. * Changed some of that math.h stuff. Gcc 2.95.2 (and pgcc) seem ok with it the way I have it now, and I didnt feel like playing with it anymore... * Tried to implement a 'large buffer' option to avoid audio breakups. Ended up with WORSE breakups. Someone wanna look that over and see what I missed? * Meanwhile, I upgraded to a nice Trident 4Dwave card and now am running with the Alsa drivers (.58a as of this writing). Program works lovely by default. (At least as long as you've got the oss emulation modules, but you do, dont you?? :) This card at least gives me the exact sample rates I ask for, but I'm sure alot of people out there still have cards which dont so I didnt touch the rate-tweak logic. If you want a large buffer and to use native alsa playback, try something like: ./ospc -p CT-1-22-TheHiddenTruth.spc | bag | aplay -m 'bag' is a nice buffering utility that I think came with Timidity's tools, and aplay is part of the Alsa stuff. Dont bother trying this approach with certain other play utilities, in particular avoid the one from sox. You can identify this crappy 'play' program by typing 'play' and seeing if it says its a frontend to sox. Sox's play just soaks up tons of cpu and does NOT help (the point of HAVING a buffer is to try to avoid cpu usage spikes from breaking up the audio, after all!!) * The dos version did not yet support the id tag's 'fadeout length' value, and I have not tried to do anything about this yet either. Feel free to do so for me. :) I was thinking maybe to use the oss or alsa mixer controls. Note that at least for my trident, the oss-emulation 'main volume' seems to be using one of trident's 32-position ones (despite showing in the oss mixers as a 1...100 range), making for rather unsmooth fading if one were to use that. In fact, all of the trident's volume knobs can get a bit confusing to sort out. There are at least several availible from alsa mixers with a full 255 position range at least. (I use xamixer. gamix is also nice. Neither is totally perfect though.)... * Some extra keypresses - q and escape quit as well as the previous spacebar. New key functions include p or s to pause. Other activity such as fast forward and rewind seem awfully difficult to implement. Feel free to try doing so yourself as always :) Note that quiting or pausing seem to take place after the buffer is emptied (or at least not QUITE instantly). Good enough though. * If you feel compelled to, make ospcshared cp -a libspc.so /usr/lib/libspc.so.0 (or any other suitable directory, or just edit your LD_LIBRARY_PATH) Works here, your milage may vary. * Changed Makefile to use CFLAGS, and included a nice flag setting for optimization which I got from who knows where (probably an old posting to the xmame mailing list).