diff --git a/Plugins/HighlyComplete/HighlyComplete.xcodeproj/project.pbxproj b/Plugins/HighlyComplete/HighlyComplete.xcodeproj/project.pbxproj index fe3e98184..f41a5ccee 100644 --- a/Plugins/HighlyComplete/HighlyComplete.xcodeproj/project.pbxproj +++ b/Plugins/HighlyComplete/HighlyComplete.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ 8360EF6E17F92E86005208A4 /* HighlyExperimental.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8360EF4417F92C92005208A4 /* HighlyExperimental.framework */; }; 8384904A180764B500E7332D /* SSEQPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83848FEC1807624000E7332D /* SSEQPlayer.framework */; }; 8384904B180764C200E7332D /* SSEQPlayer.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83848FEC1807624000E7332D /* SSEQPlayer.framework */; }; + 83D4481E18ACA5C8000F443A /* lazyusf in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83D4481B18ACA5AD000F443A /* lazyusf */; }; 83DE0CBC180B02CC00269051 /* vio2sf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83DE0C3A180A9BD500269051 /* vio2sf.framework */; }; 83DE0CBD180B02D800269051 /* vio2sf.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83DE0C3A180A9BD500269051 /* vio2sf.framework */; }; 83DE0CC0180B27C200269051 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83DE0CBF180B27C200269051 /* libz.dylib */; }; @@ -129,6 +130,16 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 83D4481A18ACA591000F443A /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 6; + files = ( + 83D4481E18ACA5C8000F443A /* lazyusf in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 83F18C3717F9300400471B6C /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -167,6 +178,7 @@ 8360EEF317F92AC8005208A4 /* HighlyComplete-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HighlyComplete-Prefix.pch"; sourceTree = "<group>"; }; 8360EF3E17F92C91005208A4 /* HighlyExperimental.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HighlyExperimental.xcodeproj; path = ../../Frameworks/HighlyExperimental/HighlyExperimental.xcodeproj; sourceTree = "<group>"; }; 83848FE61807623F00E7332D /* SSEQPlayer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SSEQPlayer.xcodeproj; path = ../../Frameworks/SSEQPlayer/SSEQPlayer.xcodeproj; sourceTree = "<group>"; }; + 83D4481B18ACA5AD000F443A /* lazyusf */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; name = lazyusf; path = ../../ThirdParty/lazyusf/lazyusf; sourceTree = "<group>"; }; 83DE0C34180A9BD400269051 /* vio2sf.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = vio2sf.xcodeproj; path = ../../Frameworks/vio2sf/vio2sf.xcodeproj; sourceTree = "<group>"; }; 83DE0CBF180B27C200269051 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -226,6 +238,7 @@ 8360EEDB17F92AC8005208A4 = { isa = PBXGroup; children = ( + 83D4481D18ACA5B1000F443A /* External */, 8360EEED17F92AC8005208A4 /* HighlyComplete */, 8360EEE617F92AC8005208A4 /* Frameworks */, 8360EEE517F92AC8005208A4 /* Products */, @@ -306,6 +319,14 @@ name = Products; sourceTree = "<group>"; }; + 83D4481D18ACA5B1000F443A /* External */ = { + isa = PBXGroup; + children = ( + 83D4481B18ACA5AD000F443A /* lazyusf */, + ); + name = External; + sourceTree = "<group>"; + }; 83DE0C35180A9BD400269051 /* Products */ = { isa = PBXGroup; children = ( @@ -325,6 +346,7 @@ 8360EEE117F92AC8005208A4 /* Frameworks */, 8360EEE217F92AC8005208A4 /* Resources */, 83F18C3717F9300400471B6C /* CopyFiles */, + 83D4481A18ACA591000F443A /* CopyFiles */, ); buildRules = ( ); diff --git a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm index e4a3274f6..d997ad90c 100644 --- a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm +++ b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm @@ -32,6 +32,10 @@ #include <zlib.h> +#include <dlfcn.h> + +// #define USF_LOG + @interface psf_file_container : NSObject { NSLock * lock; NSMutableDictionary * list; @@ -879,11 +883,16 @@ static int twosf_info(void * context, const char * name, const char * value) return 0; } -#if 0 struct usf_loader_state { +#ifdef USF_LOG FILE * log; - FILE * fLazyusf; +#endif + NSTask * task; + NSPipe * pipe_stdin; + NSPipe * pipe_stdout; + NSFileHandle * file_stdin; + NSFileHandle * file_stdout; bool donewriting; uint32_t enablecompare; uint32_t enablefifofull; @@ -891,7 +900,11 @@ struct usf_loader_state uint32_t pairsleft; usf_loader_state() - : log(NULL), fLazyusf(NULL), + : +#ifdef USF_LOG + log(NULL), +#endif + task(nil), pipe_stdin(nil), pipe_stdout(nil), enablecompare(0), enablefifofull(0), samplerate(0), pairsleft(0) { } @@ -900,64 +913,88 @@ struct usf_loader_state close(); } - void fwrite( const void * buf, ssize_t size, ssize_t count, FILE * f ) + void fwrite( const void * buf, ssize_t size, ssize_t count ) { - ::fwrite( buf, size, count, f ); + [file_stdin writeData:[NSData dataWithBytes:buf length:size * count]]; +#ifdef USF_LOG if ( log ) + { ::fwrite( buf, size, count, log ); + fflush( log ); + } +#endif + } + + ssize_t fread( void * buf, ssize_t size, ssize_t count ) + { + NSData * data = [file_stdout readDataOfLength:size * count]; + if ( data && [data length] ) + { + memcpy( buf, [data bytes], [data length] ); + return [data length] / size; + } + return 0; } void open() { close(); - + +#ifdef USF_LOG log = fopen("/tmp/lazyusf_transaction", "w"); - fLazyusf = popen( "/usr/local/bin/lazyusf", "r+" ); - fwrite( &enablecompare, sizeof(enablecompare), 1, fLazyusf ); - fwrite( &enablefifofull, sizeof(enablefifofull), 1, fLazyusf ); +#endif + Dl_info info; + dladdr( (void*) &twosf_info, &info ); + + NSString * base_path = [[NSString stringWithUTF8String:info.dli_fname] stringByDeletingLastPathComponent]; + + task = [[NSTask alloc] init]; + [task setLaunchPath:[base_path stringByAppendingPathComponent:@"lazyusf"]]; + + pipe_stdin = [[NSPipe alloc] init]; + pipe_stdout = [[NSPipe alloc] init]; + + [task setStandardInput:pipe_stdin]; + [task setStandardOutput:pipe_stdout]; + + file_stdin = [pipe_stdin fileHandleForWriting]; + file_stdout = [pipe_stdout fileHandleForReading]; + + [task launch]; + + fwrite( &enablecompare, sizeof(enablecompare), 1 ); + fwrite( &enablefifofull, sizeof(enablefifofull), 1 ); donewriting = false; } void close() { - if (fLazyusf) + if (task != nil) { uint32_t zero = 0; - fwrite( &zero, sizeof(uint32_t), 1, fLazyusf ); - pclose( fLazyusf ); + fwrite( &zero, sizeof(uint32_t), 1 ); + [task release]; + task = nil; + [pipe_stdin release]; + pipe_stdin = nil; + [pipe_stdout release]; + pipe_stdout = nil; } - fLazyusf = NULL; +#ifdef USF_LOG if (log) fclose(log); log = NULL; +#endif } bool opened() { - return fLazyusf != NULL; + return task != nil; } void write_reserved( const uint8_t * reserved, uint32_t reserved_size ) { - fwrite( &reserved_size, sizeof(reserved_size), 1, fLazyusf ); - if ( reserved_size ) fwrite( reserved, 1, reserved_size, fLazyusf ); - } - - ssize_t fread( void * buf, ssize_t size, ssize_t count, FILE * f ) - { - int d = fileno( f ); - for (;;) - { - ssize_t r = read( d, buf, size * count ); - if ( r == -1 && errno == EAGAIN ) - { - usleep( 1000 ); - continue; - } - else if ( r > 0 ) - return r / size; - else - return -1; - } + fwrite( &reserved_size, sizeof(reserved_size), 1 ); + if ( reserved_size ) fwrite( reserved, 1, reserved_size ); } BOOL read_samples( int16_t * out, uint32_t out_pairs ) @@ -965,37 +1002,35 @@ struct usf_loader_state if ( !donewriting ) { write_reserved( NULL, 0 ); - fflush( fLazyusf ); +#ifdef USF_LOG fclose( log ); log = NULL; - int d = fileno(fLazyusf); - fcntl(d, F_SETFL, fcntl(d, F_GETFL, 0) | O_NONBLOCK); +#endif donewriting = true; } while ( out_pairs ) { if ( !pairsleft ) { - if (fread( &samplerate, sizeof(samplerate), 1, fLazyusf ) < 0) return NO; - if (fread( &pairsleft, sizeof(pairsleft), 1, fLazyusf ) < 0) return NO; + if (fread( &samplerate, sizeof(samplerate), 1 ) < 1) return NO; + if (fread( &pairsleft, sizeof(pairsleft), 1 ) < 1) return NO; pairsleft >>= 1; } if ( pairsleft ) { - if ( pairsleft >= out_pairs ) + if ( pairsleft > out_pairs ) { - if (fread( out, sizeof(int16_t) * 2, out_pairs, fLazyusf ) < 0) return NO; + if (fread( out, sizeof(int16_t) * 2, out_pairs ) < out_pairs) return NO; pairsleft -= out_pairs; return YES; } - if (fread( out, sizeof(int16_t) * 2, pairsleft, fLazyusf ) < 0) return NO; + if (fread( out, sizeof(int16_t) * 2, pairsleft ) < pairsleft) return NO; out += pairsleft * 2; out_pairs -= pairsleft; pairsleft = 0; uint32_t one = 1; - fwrite( &one, sizeof(one), 1, fLazyusf ); - fflush( fLazyusf ); + fwrite( &one, sizeof(one), 1 ); } } return YES; @@ -1029,7 +1064,6 @@ static int usf_info(void * context, const char * name, const char * value) return 0; } -#endif - (BOOL)initializeDecoder { @@ -1098,7 +1132,6 @@ static int usf_info(void * context, const char * name, const char * value) free( state.data ); } -#if 0 else if ( type == 0x21 ) { struct usf_loader_state * uUsf = new usf_loader_state; @@ -1108,7 +1141,6 @@ static int usf_info(void * context, const char * name, const char * value) if ( psf_load( [currentUrl UTF8String], &source_callbacks, 0x21, usf_loader, uUsf, usf_info, uUsf ) <= 0 ) return NO; } -#endif else if ( type == 0x22 ) { struct gsf_loader_state state; @@ -1383,7 +1415,6 @@ static int usf_info(void * context, const char * name, const char * value) sega_execute( emulatorCore, 0x7fffffff, ( int16_t * ) buf, &howmany ); frames = howmany; } -#if 0 else if ( type == 0x21 ) { struct usf_loader_state * uUsf = ( struct usf_loader_state * ) emulatorCore; @@ -1393,7 +1424,6 @@ static int usf_info(void * context, const char * name, const char * value) sampleRate = uUsf->samplerate; } -#endif else if ( type == 0x22 ) { GBASystem * system = ( GBASystem * ) emulatorCore; @@ -1507,13 +1537,10 @@ static int usf_info(void * context, const char * name, const char * value) - (void)closeDecoder { if ( emulatorCore ) { -#if 0 if ( type == 0x21 ) { struct usf_loader_state * uUsf = ( struct usf_loader_state * ) emulatorCore; delete uUsf; - } else -#endif - if ( type == 0x22 ) { + } else if ( type == 0x22 ) { GBASystem * system = ( GBASystem * ) emulatorCore; CPUCleanUp( system ); soundShutdown( system ); @@ -1604,7 +1631,6 @@ static int usf_info(void * context, const char * name, const char * value) } while (framesRead < frame); } -#if 0 else if ( type == 0x21 ) { struct usf_loader_state * uUsf = ( struct usf_loader_state * ) emulatorCore; @@ -1617,7 +1643,6 @@ static int usf_info(void * context, const char * name, const char * value) framesRead += howmany; } while (framesRead < frame); } -#endif else if ( type == 0x22 ) { GBASystem * system = ( GBASystem * ) emulatorCore; @@ -1739,11 +1764,7 @@ static int usf_info(void * context, const char * name, const char * value) + (NSArray *)fileTypes { - return [NSArray arrayWithObjects:@"psf",@"minipsf",@"psf2", @"minipsf2", @"ssf", @"minissf", @"dsf", @"minidsf", @"qsf", @"miniqsf", @"gsf", @"minigsf", @"ncsf", @"minincsf", @"2sf", @"mini2sf", -#if 0 - @"usf", @"miniusf", -#endif - nil]; + return [NSArray arrayWithObjects:@"psf",@"minipsf",@"psf2", @"minipsf2", @"ssf", @"minissf", @"dsf", @"minidsf", @"qsf", @"miniqsf", @"gsf", @"minigsf", @"ncsf", @"minincsf", @"2sf", @"mini2sf", @"usf", @"miniusf", nil]; } + (NSArray *)mimeTypes diff --git a/ThirdParty/lazyusf/lazyusf b/ThirdParty/lazyusf/lazyusf new file mode 100755 index 000000000..dbd8827ff Binary files /dev/null and b/ThirdParty/lazyusf/lazyusf differ