added sound, and did various other minor things to the cocoa port
This commit is contained in:
parent
312bdff914
commit
aeea42a141
|
@ -9,6 +9,7 @@
|
|||
- Added option to disable execution upon loading. [Jeff B]
|
||||
- Many more strings are translatable now. [Jeff B]
|
||||
- Default screen color now black (better represents being "off" and easier on eyes at night) [Jeff B]
|
||||
- Added sound [Jeff B]
|
||||
general:
|
||||
- Fixed possible segfault in ROMReader on ia64 and amd64. [evilynux]
|
||||
- Fixed a crash bug with 2D background corrupting memory [shash]
|
||||
|
|
|
@ -3,29 +3,75 @@
|
|||
<FileVersion major="1" minor="6" />
|
||||
<Project>
|
||||
<Option title="DeSmuME Cocoa" />
|
||||
<Option platforms="Mac;" />
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Option show_notes="0">
|
||||
<notes>
|
||||
<![CDATA[DeSmuME
|
||||
|
||||
Cocoa Port
|
||||
|
||||
DeSmuME is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DeSmuME is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DeSmuME; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA]]>
|
||||
</notes>
|
||||
</Option>
|
||||
<Build>
|
||||
<Target title="Cocoa">
|
||||
<Target title="Cocoa X86">
|
||||
<Option platforms="Mac;" />
|
||||
<Option output="DeSmuME.app/Contents/MacOS/DeSmuME" prefix_auto="0" extension_auto="0" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="0" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-march=pentium-m" />
|
||||
<Add option="-arch i386" />
|
||||
<Add option="-DDESMUME_COCOA" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-framework Cocoa" />
|
||||
<Add option="-framework OpenGL" />
|
||||
<Add option="-framework CoreAudio" />
|
||||
<Add option="-framework AudioUnit" />
|
||||
<Add option="-framework AudioToolbox" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Cocoa PPC">
|
||||
<Option platforms="Mac;" />
|
||||
<Option output="DeSmuME.app/Contents/MacOS/DeSmuME" prefix_auto="0" extension_auto="0" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-DDESMUME_COCOA" />
|
||||
<Add option="-DWORDS_BIGENDIAN" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-framework Cocoa" />
|
||||
<Add option="-framework OpenGL" />
|
||||
<Add option="-framework CoreAudio" />
|
||||
<Add option="-framework AudioUnit" />
|
||||
<Add option="-framework AudioToolbox" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
<VirtualTargets>
|
||||
<Add alias="Cocoa Universal" targets="Cocoa X86;Cocoa PPC;" />
|
||||
</VirtualTargets>
|
||||
<Compiler>
|
||||
<Add option="-fexpensive-optimizations" />
|
||||
<Add option="-O3" />
|
||||
<Add option="-Wall" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
|
@ -104,6 +150,11 @@
|
|||
<Option compile="1" />
|
||||
<Option link="1" />
|
||||
</Unit>
|
||||
<Unit filename="sndOSX.h" />
|
||||
<Unit filename="sndOSX.m">
|
||||
<Option compile="1" />
|
||||
<Option link="1" />
|
||||
</Unit>
|
||||
<Unit filename="../config.h" />
|
||||
<Unit filename="../cp15.c">
|
||||
<Option compilerVar="CC" />
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
|
||||
#import "globals.h"
|
||||
|
||||
void setTitle(int i)
|
||||
{
|
||||
[main_window setTitle:[NSString stringWithFormat:@"%d", i]];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//Menu Item implementation--------------------------------------
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
@ -73,7 +78,7 @@ NSString* openDialog(NSArray *file_types)
|
|||
[panel setCanChooseFiles:YES];
|
||||
[panel setAllowsMultipleSelection:NO];
|
||||
|
||||
if([panel runModalForDirectory:@"/Users/gecko/nds" file:nil types:file_types] == NSOKButton)
|
||||
if([panel runModalForDirectory:nil file:nil types:file_types] == NSOKButton)
|
||||
{
|
||||
//a file was selected
|
||||
|
||||
|
|
|
@ -114,6 +114,10 @@ extern NSMenuItem *reset_item;
|
|||
extern NSMenuItem *save_state_as_item;
|
||||
extern NSMenuItem *load_state_from_item;
|
||||
|
||||
//sound (defined/managed in nds_control.m)
|
||||
extern NSMenuItem *volume_item[10];
|
||||
extern NSMenuItem *mute_item;
|
||||
|
||||
#define SAVE_SLOTS 10 //this should never be more than NB_SAVES in saves.h
|
||||
extern NSMenuItem *saveSlot_item[SAVE_SLOTS];
|
||||
extern NSMenuItem *loadSlot_item[SAVE_SLOTS];
|
||||
|
@ -143,6 +147,9 @@ extern NintendoDS *NDS;
|
|||
extern VideoOutputWindow *main_window;
|
||||
|
||||
void setAppDefaults(); //this is defined in preferences.m and should be called at app launch
|
||||
|
||||
void clearEvents(bool wait);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
extern volatile int /*desmume_BOOL*/ execute;
|
||||
|
|
|
@ -30,7 +30,6 @@ Based on work by yopyop and the DeSmuME team!
|
|||
|
||||
//DeSmuME general includes
|
||||
#define OBJ_C
|
||||
#include "../SPU.h"
|
||||
#include "../render3D.h"
|
||||
#include "../GPU.h"
|
||||
#include "../Windows/OGLRender.h"
|
||||
|
@ -44,7 +43,8 @@ FIXME: Hardware acceleration for openglrender.c ??
|
|||
FIXME: When cross-platform (core) components end emulation due to error - pause should be called (set the menu checkmark)
|
||||
FIXME: Some bug where states get messed up and hitting execute does nothing......
|
||||
FIXME: .nds.gba extensions don't work in open panels
|
||||
FIXME: Traveling windows when constantly resizing with hotkey
|
||||
FIXME: Traveling windows when constantly resizing
|
||||
FIXME: Show version number somewhere in the program
|
||||
*/
|
||||
|
||||
//Globals----------------------------------------------------------------------------------------
|
||||
|
@ -94,13 +94,6 @@ volatile desmume_BOOL execute = FALSE;
|
|||
volatile BOOL finished = FALSE;
|
||||
volatile BOOL paused = TRUE;
|
||||
|
||||
SoundInterface_struct *SNDCoreList[] = {
|
||||
&SNDDummy,
|
||||
//&SNDFile,
|
||||
//&SNDDIRECTX,
|
||||
NULL
|
||||
};
|
||||
|
||||
GPU3DInterface *core3DList[] = {
|
||||
&gpu3DNull,
|
||||
&gpu3Dgl
|
||||
|
@ -114,7 +107,7 @@ NintendoDS *NDS;
|
|||
void Quit()
|
||||
{
|
||||
//stop emulation if it's going
|
||||
[NDS pause];
|
||||
[NDS destroy];
|
||||
|
||||
//
|
||||
finished = true;
|
||||
|
@ -142,7 +135,7 @@ NSEvent *current_event;
|
|||
//if wait is true then it will sit around waiting for an
|
||||
//event for a short period of time taking up very little CPU
|
||||
//(use when game is not running)
|
||||
inline void clearEvents(bool wait)
|
||||
void clearEvents(bool wait)
|
||||
{
|
||||
//wait for the next event
|
||||
while((current_event = [NSApp nextEventMatchingMask:0 untilDate:wait?[NSDate dateWithTimeIntervalSinceNow:.2]:nil inMode:NSDefaultRunLoopMode dequeue:YES]))
|
||||
|
@ -162,6 +155,7 @@ void CreateMenu()
|
|||
NSMenu* file;
|
||||
NSMenu* emulation;
|
||||
NSMenu* view;
|
||||
NSMenu* sound_menu;
|
||||
//NSMenu* window;
|
||||
NSMenu* help;
|
||||
|
||||
|
@ -229,6 +223,7 @@ void CreateMenu()
|
|||
NSMenuItem *file_item = [menu addItemWithTitle:@"File" action:action keyEquivalent:@""];
|
||||
NSMenuItem *emulation_item = [menu addItemWithTitle:@"Emulation" action:action keyEquivalent:@""];
|
||||
NSMenuItem *view_item = [menu addItemWithTitle:@"View" action:action keyEquivalent:@""];
|
||||
NSMenuItem *sound_item = [menu addItemWithTitle:@"Sound" action:action keyEquivalent:@""];
|
||||
//NSMenuItem *window_item = [menu addItemWithTitle:@"Window" action:action keyEquivalent:@""];
|
||||
NSMenuItem *help_item = [menu addItemWithTitle:@"Help" action:action keyEquivalent:@""];
|
||||
|
||||
|
@ -508,7 +503,40 @@ a way to get the time of a save that's not a string / human formatted...
|
|||
allows_resize_item = [view addItemWithTitle:@"Screenshot to Window" action:@selector(screenShotToWindow) keyEquivalent:@""];
|
||||
[allows_resize_item setTarget:main_window];
|
||||
|
||||
//Create the sound menu
|
||||
sound_menu = [[NSMenu alloc] initWithTitle:localizedString(@"Sound", nil)];
|
||||
[menu setSubmenu:sound_menu forItem:sound_item];
|
||||
|
||||
temp = [sound_menu addItemWithTitle:@"Volume" action:nil keyEquivalent:@""];
|
||||
[temp setTarget:NSApp];
|
||||
|
||||
NSMenu *volume_menu = [[NSMenu alloc] initWithTitle:localizedString(@"Volume", nil)];
|
||||
[sound_menu setSubmenu:volume_menu forItem:temp];
|
||||
|
||||
for(i = 0; i < 10; i++)
|
||||
{
|
||||
volume_item[i] = [volume_menu addItemWithTitle:@"Volume %d" withInt:(i+1)*10 action:@selector(setVolume:) keyEquivalent:@""];
|
||||
[volume_item[i] setTarget:NDS];
|
||||
if(i == 9)
|
||||
[volume_item[i] setState:NSOnState]; //check 100% volume since it's defaults
|
||||
}
|
||||
|
||||
[sound_menu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
mute_item = [sound_menu addItemWithTitle:@"Mute" action:@selector(toggleMuting) keyEquivalent:@""];
|
||||
[mute_item setTarget:NDS];
|
||||
/*
|
||||
[sound_menu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
temp = [sound_menu addItemWithTitle:@"Record to File..." action:@selector(chooseSoundOutputFile) keyEquivalent: @"r"];
|
||||
[temp setTarget:NDS];
|
||||
|
||||
temp = [sound_menu addItemWithTitle:@"Pause Recording" action:@selector(startRecording) keyEquivalent: @""];
|
||||
[temp setTarget:NDS];
|
||||
|
||||
temp = [sound_menu addItemWithTitle:@"Save Recording" action:@selector(pauseRecording) keyEquivalent: @""];
|
||||
[temp setTarget:NDS];
|
||||
*/
|
||||
//Create the window menu
|
||||
/*
|
||||
window = [[NSMenu alloc] initWithTitle:localizedString(@"Window", nil)];
|
||||
|
|
|
@ -24,10 +24,14 @@
|
|||
|
||||
//This class manages emulation
|
||||
//dont instanciate more than once!
|
||||
@interface NintendoDS : NSObject {}
|
||||
@interface NintendoDS : NSObject
|
||||
{
|
||||
BOOL muted;
|
||||
}
|
||||
|
||||
//creation
|
||||
//
|
||||
- (id)init;
|
||||
- (id)destroy;
|
||||
|
||||
//Firmware control
|
||||
- (void)setPlayerName:(NSString*)player_name;
|
||||
|
@ -56,6 +60,14 @@
|
|||
|
||||
//
|
||||
- (void)showRomInfo;
|
||||
|
||||
//sound
|
||||
- (void)setVolume:(id)sender;
|
||||
- (void)toggleMuting;
|
||||
- (void)chooseSoundOutputFile;
|
||||
- (void)startRecording;
|
||||
- (void)pauseRecording;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
//DeSmuME general includes
|
||||
#define OBJ_C
|
||||
#include "sndOSX.h"
|
||||
#include "../NDSSystem.h"
|
||||
#include "../saves.h"
|
||||
#undef BOOL
|
||||
|
@ -33,7 +34,17 @@
|
|||
//times one million for microseconds per frame
|
||||
#define DS_MICROSECONDS_PER_FRAME (1.0 / 59.8) * 1000000.0
|
||||
|
||||
//fixme bug when hitting apple+Q during the open dialog
|
||||
SoundInterface_struct *SNDCoreList[] = {
|
||||
&SNDDummy,
|
||||
&SNDFile,
|
||||
&SNDOSX,
|
||||
NULL
|
||||
};
|
||||
|
||||
@interface SoundSavePanel : NSSavePanel
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@interface TableHelper : NSObject
|
||||
{
|
||||
|
@ -75,6 +86,9 @@ NSMenuItem *rom_info_item;
|
|||
NSMenuItem *frame_skip_auto_item;
|
||||
NSMenuItem *frame_skip_item[MAX_FRAME_SKIP];
|
||||
|
||||
NSMenuItem *volume_item[10];
|
||||
NSMenuItem *mute_item;
|
||||
|
||||
volatile u8 frame_skip = 0; //this is one more than the acutal frame skip, a value of 0 signifies auto frame skip
|
||||
|
||||
static int backupmemorytype=MC_TYPE_AUTODETECT;
|
||||
|
@ -93,17 +107,27 @@ NSString *current_file;
|
|||
struct armcpu_ctrl_iface *arm7_ctrl_iface;
|
||||
//struct configured_features my_config;
|
||||
|
||||
NDS_Init( arm9_memio, &arm9_ctrl_iface,
|
||||
arm7_memio, &arm7_ctrl_iface);
|
||||
NDS_Init(/*arm9_memio, &arm9_ctrl_iface, arm7_memio, &arm7_ctrl_iface*/);
|
||||
|
||||
NDS_FillDefaultFirmwareConfigData(&firmware);
|
||||
[self setPlayerName:@"Joe"];
|
||||
[self setPlayerName:@"Joe"]; //fixme
|
||||
NDS_CreateDummyFirmware(&firmware);
|
||||
|
||||
if(SPU_ChangeSoundCore(SNDCORE_OSX, 735 * 4) != 0)
|
||||
{
|
||||
messageDialog(localizedString(@"Error", nil), @"Unable to initialize sound core");
|
||||
}
|
||||
|
||||
SPU_SetVolume(100);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)destroy
|
||||
{
|
||||
NDS_DeInit();
|
||||
}
|
||||
|
||||
- (void)setPlayerName:(NSString*)player_name
|
||||
{
|
||||
//first we convert to UTF-16 which the DS uses to store the nickname
|
||||
|
@ -141,7 +165,7 @@ NSString *current_file;
|
|||
[self pause];
|
||||
|
||||
//load the rom
|
||||
if(!NDS_LoadROM([filename cStringUsingEncoding:NSASCIIStringEncoding], backupmemorytype, backupmemorysize, "/Users/gecko/AAAA.sav") > 0)
|
||||
if(!NDS_LoadROM([filename cStringUsingEncoding:NSASCIIStringEncoding], backupmemorytype, backupmemorysize, "temp.sav") > 0)
|
||||
{
|
||||
//if it didn't work give an error and dont unpause
|
||||
messageDialog(localizedString(@"Error", nil), @"Could not open file");
|
||||
|
@ -326,7 +350,6 @@ NSString *current_file;
|
|||
bool was_running = false; //initialized here to avoid a warning
|
||||
|
||||
unsigned long long frame_start_time, frame_end_time;
|
||||
unsigned long long microseconds_per_frame;
|
||||
|
||||
int frames_to_skip = 0;
|
||||
|
||||
|
@ -354,6 +377,8 @@ NSString *current_file;
|
|||
Microseconds((struct UnsignedWide*)&frame_start_time);
|
||||
|
||||
cycles = NDS_exec((560190<<1)-cycles, FALSE);
|
||||
SPU_Emulate();
|
||||
|
||||
|
||||
if(frames_to_skip != 0)
|
||||
frames_to_skip--;
|
||||
|
@ -539,8 +564,80 @@ NSString *current_file;
|
|||
if(!was_paused)[self execute];
|
||||
}
|
||||
|
||||
- (void)setVolume:(id)sender
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 10; i++)
|
||||
{
|
||||
if(sender == volume_item[i])
|
||||
{
|
||||
[volume_item[i] setState:NSOnState];
|
||||
SNDOSXSetVolume((i+1)*10);
|
||||
} else
|
||||
[volume_item[i] setState:NSOffState];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)toggleMuting
|
||||
{
|
||||
if([mute_item state] == NSOffState)
|
||||
{
|
||||
[mute_item setState:NSOnState];
|
||||
SNDOSXMuteAudio();
|
||||
} else
|
||||
{
|
||||
[mute_item setState:NSOffState];
|
||||
|
||||
//find and restore volume
|
||||
int i;
|
||||
for(i = 0; i < 10; i++)
|
||||
if([volume_item[i] state] == NSOnState)
|
||||
SNDOSXSetVolume((i+1)*10);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)chooseSoundOutputFile
|
||||
{
|
||||
NSSavePanel *panel = [NSSavePanel savePanel];
|
||||
|
||||
//fixme localize
|
||||
[panel setTitle:@"Record Audio to File..."];
|
||||
|
||||
/*
|
||||
[panel beginSheetForDirectory:@"" file:@"DeSmuMEaudio.wav" modalForWindow:main_window modalDelegate:self
|
||||
didEndSelector:nil contextInfo:nil];
|
||||
*/
|
||||
//[panel setMessage:@"Please choose an audio file to record sound output to"];
|
||||
//[panel setNameFieldLabel:@"BAL"];
|
||||
[panel runModal];
|
||||
|
||||
//[NSApp runModalforWindow:panel];
|
||||
|
||||
if(!SNDOSXOpenFile([panel filename]))
|
||||
{
|
||||
messageDialog(localizedString(@"Error", nil), @"Couldn't create sound recording output file");
|
||||
return;
|
||||
}
|
||||
|
||||
SNDOSXStartRecording();
|
||||
|
||||
}
|
||||
|
||||
- (void)startRecording
|
||||
{
|
||||
SNDOSXStartRecording();
|
||||
}
|
||||
|
||||
- (void)pauseRecording
|
||||
{
|
||||
SNDOSXStopRecording();
|
||||
}
|
||||
|
||||
@end
|
||||
#define ROM_INFO_ROWS 9
|
||||
|
||||
//Rom info helper stuff -------------------------------------------------------------
|
||||
|
||||
#define ROM_INFO_ROWS 8
|
||||
#define ROM_INFO_WIDTH 400
|
||||
@implementation TableHelper
|
||||
- (id)initWithWindow:(NSWindow*)window
|
||||
|
@ -549,7 +646,7 @@ NSString *current_file;
|
|||
|
||||
type_column = [[NSTableColumn alloc] initWithIdentifier:@""];
|
||||
[type_column setEditable:NO];
|
||||
[value_column setResizable:YES];
|
||||
[type_column setResizable:YES];
|
||||
[[type_column headerCell] setStringValue:@"Attribute"];
|
||||
[type_column setMinWidth: 1];
|
||||
|
||||
|
@ -618,33 +715,30 @@ if([table headerView] == nil)messageDialogBlank();
|
|||
if(aTableColumn == type_column)
|
||||
{
|
||||
if(rowIndex == 0)
|
||||
return localizedString(@"File on Disc", @" ROM Info ");
|
||||
return localizedString(@"File", @" ROM Info ");
|
||||
|
||||
if(rowIndex == 1)
|
||||
return localizedString(@"ROM Title", @" ROM Info ");
|
||||
return localizedString(@"Title", @" ROM Info ");
|
||||
|
||||
if(rowIndex == 2)
|
||||
return localizedString(@"Maker Code", @" ROM Info ");
|
||||
return localizedString(@"Maker", @" ROM Info ");
|
||||
|
||||
if(rowIndex == 3)
|
||||
return localizedString(@"Unit Code", @" ROM Info ");
|
||||
return localizedString(@"Size", @" ROM Info ");
|
||||
|
||||
if(rowIndex == 4)
|
||||
return localizedString(@"Card Size", @" ROM Info ");
|
||||
return localizedString(@"ARM9 Size", @" ROM Info ");
|
||||
|
||||
if(rowIndex == 5)
|
||||
return localizedString(@"Flags", @" ROM Info ");
|
||||
return localizedString(@"ARM7 Size", @" ROM Info ");
|
||||
|
||||
if(rowIndex == 6)
|
||||
return localizedString(@"Size of ARM9 Binary", @" ROM Info ");
|
||||
return localizedString(@"Data Size", @" ROM Info ");
|
||||
|
||||
if(rowIndex == 7)
|
||||
return localizedString(@"Size of ARM7 Size", @" ROM Info ");
|
||||
|
||||
if(rowIndex == 8)
|
||||
return localizedString(@"Size of Data", @" ROM Info ");
|
||||
return localizedString(@"Icon", @" ROM Info ");
|
||||
} else
|
||||
{
|
||||
{//units?
|
||||
if(rowIndex == 0)return current_file;
|
||||
|
||||
if(rowIndex == 1)
|
||||
|
@ -652,47 +746,37 @@ if([table headerView] == nil)messageDialogBlank();
|
|||
|
||||
if(rowIndex == 2)
|
||||
{
|
||||
if(header->makerCode == 12592)
|
||||
return NSSTRc("Nintendo");
|
||||
|
||||
return [NSString localizedStringWithFormat:@"%u", header->makerCode];
|
||||
}
|
||||
|
||||
if(rowIndex == 3)
|
||||
{
|
||||
return [NSString localizedStringWithFormat:@"%u", header->unitCode];
|
||||
}
|
||||
|
||||
if(rowIndex == 4)
|
||||
{//fixe: should show units?
|
||||
return [NSString localizedStringWithFormat:@"%u", header->cardSize];
|
||||
}
|
||||
|
||||
if(rowIndex == 5)
|
||||
{//always seems to be empty?
|
||||
return [NSString localizedStringWithFormat:@"%u%u%u%u%u%u%u%u",
|
||||
((header->flags) & 0x01) >> 0,
|
||||
((header->flags) & 0x02) >> 1,
|
||||
((header->flags) & 0x04) >> 2,
|
||||
((header->flags) & 0x08) >> 3,
|
||||
((header->flags) & 0x10) >> 4,
|
||||
((header->flags) & 0x20) >> 5,
|
||||
((header->flags) & 0x40) >> 6,
|
||||
((header->flags) & 0x80) >> 7];
|
||||
}
|
||||
|
||||
if(rowIndex == 6)
|
||||
{//fixe: should show units?
|
||||
if(rowIndex == 4)
|
||||
{
|
||||
return [NSString localizedStringWithFormat:@"%u", header->ARM9binSize];
|
||||
}
|
||||
|
||||
if(rowIndex == 7)
|
||||
{//fixe: should show units?
|
||||
if(rowIndex == 5)
|
||||
{
|
||||
return [NSString localizedStringWithFormat:@"%u", header->ARM7binSize];
|
||||
}
|
||||
|
||||
if(rowIndex == 8)
|
||||
{//fixe: should show units?
|
||||
if(rowIndex == 6)
|
||||
{
|
||||
return [NSString localizedStringWithFormat:@"%u", header->ARM7binSize + header->ARM7src];
|
||||
}
|
||||
|
||||
if(rowIndex == 7)
|
||||
{
|
||||
return @"NOT FINISHED";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return @"If you see this, there is a bug";
|
||||
|
|
|
@ -40,7 +40,6 @@ NSDictionary *preferences_font_attribs;
|
|||
|
||||
NSTabViewItem *interface_pane_tab;
|
||||
NSTabViewItem *firmware_pane_tab;
|
||||
NSTabViewItem *plugins_pane_tab;
|
||||
|
||||
NSText *language_selection_text;
|
||||
NSPopUpButton *language_selection;
|
||||
|
@ -377,24 +376,12 @@ void setAppDefaults()
|
|||
[tab_view addTabViewItem:firmware_pane_tab];
|
||||
|
||||
NSDictionary *firmware_options = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSArray arrayWithObjects:@"Text", [NSData dataWithBytes:&@selector(playerName:) length:sizeof(SEL)], nil], PREF_FIRMWARE_PLAYER_NAME,
|
||||
[NSArray arrayWithObjects:@"Array", [NSData dataWithBytes:&@selector(nonexisant:) length:sizeof(SEL)], @"Danish",@"English",@"French",nil], PREF_FIRMWARE_LANGUAGE,
|
||||
//[NSAsrray arrayWithObjects:@"Text", [NSData dataWithBytes:&@selector(playerName:) length:sizeof(SEL)], nil], PREF_FIRMWARE_PLAYER_NAME,
|
||||
//[NSArray arrayWithObjects:@"Array", [NSData dataWithBytes:&@selector(nonexisant:) length:sizeof(SEL)], @"Japanese",@"English",@"French",@"German",@"Italian",@"Spanish",nil], PREF_FIRMWARE_LANGUAGE,
|
||||
nil];
|
||||
|
||||
NSView *firmware_view = createPreferencesView(firmware_pane_tab, firmware_options, delegate);
|
||||
|
||||
//Create the "Plugins" pane
|
||||
plugins_pane_tab = [[NSTabViewItem alloc] initWithIdentifier:nil];
|
||||
[plugins_pane_tab setLabel:localizedString(@"Plugins", nil)];
|
||||
[tab_view addTabViewItem:plugins_pane_tab];
|
||||
|
||||
NSDictionary *plugin_options = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSArray arrayWithObjects:@"Array", [NSData dataWithBytes:&@selector(nonexisant:) length:sizeof(SEL)], @"OpenGL 3D",nil], PREF_3D_PLUGIN,
|
||||
[NSArray arrayWithObjects:@"Array", [NSData dataWithBytes:&@selector(nonexisant:) length:sizeof(SEL)], @"None",nil], PREF_SOUND_PLUGIN,
|
||||
nil];
|
||||
|
||||
NSView *plugins_view = createPreferencesView(plugins_pane_tab, plugin_options, delegate);
|
||||
|
||||
}
|
||||
|
||||
//make the window controller
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
NSPopUpButton *format_button;
|
||||
}
|
||||
|
||||
- (id)initWithBuffer:(u8*)buffer rotation:(u8)rotation saveOnly:(BOOL)save_only;
|
||||
- (id)initWithBuffer:(const u8*)buffer rotation:(u8)rotation saveOnly:(BOOL)save_only;
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/* Copyright 2007 Jeff Bland
|
||||
|
||||
This file is part of DeSmuME.
|
||||
|
||||
DeSmuME is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DeSmuME is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DeSmuME; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef SNDOSX_H
|
||||
#define SNDOSX_H
|
||||
|
||||
#include "../SPU.h"
|
||||
|
||||
#define SNDCORE_OSX 58325 //hopefully this is unique number
|
||||
|
||||
//This is the sound inerface so the emulator core can send us sound info and whatnot
|
||||
extern SoundInterface_struct SNDOSX;
|
||||
|
||||
//Beyond this point are sound interface extensions specific to the mac port
|
||||
|
||||
//recording to file
|
||||
bool SNDOSXOpenFile(void *fname); //opens a file for recording (if filename is the currently opened one, it will restart the file), fname is an NSString
|
||||
void SNDOSXStartRecording(); //begins recording to the currently open file if there is an open file
|
||||
void SNDOSXStopRecording(); //pauses recording (you can continue recording later)
|
||||
void SNDOSXCloseFile(); //closes the file, making sure it's saved
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,483 @@
|
|||
/* Copyright 2007 Jeff Bland
|
||||
|
||||
This file is part of DeSmuME
|
||||
|
||||
DeSmuME is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DeSmuME is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DeSmuME; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
//external includes
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
#include <AudioToolbox/AudioToolBox.h>
|
||||
|
||||
//desmume includes
|
||||
#define OBJ_C
|
||||
#include "sndOSX.h"
|
||||
#undef BOOL
|
||||
|
||||
//globals
|
||||
AudioUnit output_unit = NULL; //pointer to our audio device
|
||||
UInt16 *sound_data = NULL; //buffer where we hold data between getting it from the emulator and sending it to the device
|
||||
u32 sound_buffer_size; //size in bytes of sound_data
|
||||
volatile u32 sound_offset; //position in the buffer that we have copied to from the emu
|
||||
volatile u32 sound_position; //position in the buffer that we have played to
|
||||
|
||||
volatile bool mix_sound = false; //if false, our sound callback will do nothing
|
||||
volatile bool in_mix = false; //should probably use a real mutex instead but this seems to work
|
||||
|
||||
float current_volume_scalar = 100; //for volume/muting
|
||||
|
||||
//file output
|
||||
volatile bool file_open = false;
|
||||
ExtAudioFileRef outfile;
|
||||
|
||||
//defines
|
||||
#define SAMPLE_SIZE (sizeof(s16) * 2) //16 bit samples, stereo sound
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//This is the callback where we will stick the sound data we've gotten from
|
||||
//the emulator into a core audio buffer to be processed and sent to the sound driver
|
||||
|
||||
OSStatus soundMixer(
|
||||
void *inRefCon,
|
||||
AudioUnitRenderActionFlags *ioActionFlags,
|
||||
const AudioTimeStamp *inTimeStamp,
|
||||
UInt32 inBusNumber,
|
||||
UInt32 inNumberFrames,
|
||||
AudioBufferList *ioData)
|
||||
{
|
||||
//printf("SOUND CALLBACK %u off%u pos%u\n", inNumberFrames * 4, sound_offset, sound_position);
|
||||
|
||||
if(!mix_sound)
|
||||
return noErr;
|
||||
|
||||
in_mix = true;
|
||||
|
||||
UInt32 bytes_to_copy = inNumberFrames * 4;
|
||||
UInt8 *data_output = (UInt8*)ioData->mBuffers[0].mData;
|
||||
UInt8 *data_input = (UInt8*)sound_data;
|
||||
|
||||
if(sound_position == sound_offset)
|
||||
{//buffer empty
|
||||
|
||||
memset(data_output, 0, bytes_to_copy);
|
||||
|
||||
} else
|
||||
{ //buffer is not empty
|
||||
|
||||
int x;
|
||||
for(x = 0; x < bytes_to_copy; x++)
|
||||
{
|
||||
sound_position++;
|
||||
|
||||
if(sound_position >= sound_buffer_size)sound_position = 0;
|
||||
|
||||
if(sound_position == sound_offset)
|
||||
{
|
||||
sound_position --;
|
||||
memset(&data_output[x], 0, bytes_to_copy - x);
|
||||
break;
|
||||
}
|
||||
|
||||
data_output[x] = data_input[sound_position];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//copy to other channels
|
||||
UInt32 channel;
|
||||
for (channel = 1; channel < ioData->mNumberBuffers; channel++)
|
||||
memcpy(ioData->mBuffers[channel].mData, ioData->mBuffers[0].mData, ioData->mBuffers[0].mDataByteSize);
|
||||
|
||||
//record to file
|
||||
if(file_open)
|
||||
ExtAudioFileWrite(outfile, inNumberFrames, ioData);
|
||||
|
||||
in_mix = false;
|
||||
return noErr;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int SNDOSXInit(int buffer_size)
|
||||
{
|
||||
OSStatus err = noErr;
|
||||
|
||||
//Setup the sound buffer -------------------------------------------
|
||||
|
||||
//add one more since sound position can never catch up to
|
||||
//sound_offset - because if they were the same it would signify
|
||||
//that the buffer is emptys
|
||||
buffer_size += 1;
|
||||
|
||||
if((sound_data = (UInt16*)malloc(buffer_size)) == NULL)
|
||||
return -1;
|
||||
|
||||
sound_buffer_size = buffer_size;
|
||||
|
||||
SNDOSXReset();
|
||||
|
||||
//grab the default audio unit -------------------------
|
||||
|
||||
ComponentDescription desc;
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
|
||||
Component comp = FindNextComponent(NULL, &desc);
|
||||
if (comp == NULL)
|
||||
return -1;
|
||||
|
||||
err = OpenAComponent(comp, &output_unit);
|
||||
if (comp == NULL)
|
||||
return -1;
|
||||
|
||||
//then setup the callback where we will send the audio -------
|
||||
|
||||
AURenderCallbackStruct callback;
|
||||
callback.inputProc = soundMixer;
|
||||
callback.inputProcRefCon = NULL;
|
||||
|
||||
err = AudioUnitSetProperty(
|
||||
output_unit,
|
||||
kAudioUnitProperty_SetRenderCallback,
|
||||
kAudioUnitScope_Input,
|
||||
0,
|
||||
&callback,
|
||||
sizeof(callback)
|
||||
);
|
||||
|
||||
if(err != noErr)
|
||||
return -1;
|
||||
|
||||
//now begin running the audio unit-- ----------------------
|
||||
|
||||
AudioStreamBasicDescription audio_format;
|
||||
audio_format.mSampleRate = 44100;
|
||||
audio_format.mFormatID = kAudioFormatLinearPCM;
|
||||
audio_format.mFormatFlags = kAudioFormatFlagIsSignedInteger
|
||||
| kAudioFormatFlagsNativeEndian
|
||||
| kLinearPCMFormatFlagIsPacked;
|
||||
audio_format.mBytesPerPacket = 4;
|
||||
audio_format.mFramesPerPacket = 1;
|
||||
audio_format.mBytesPerFrame = 4;
|
||||
audio_format.mChannelsPerFrame = 2;
|
||||
audio_format.mBitsPerChannel = 16;
|
||||
|
||||
err = AudioUnitSetProperty(
|
||||
output_unit,
|
||||
kAudioUnitProperty_StreamFormat,
|
||||
kAudioUnitScope_Input,
|
||||
0,
|
||||
&audio_format,
|
||||
sizeof(audio_format)
|
||||
);
|
||||
|
||||
if(err != noErr){return -1;}
|
||||
|
||||
// Initialize unit
|
||||
err = AudioUnitInitialize(output_unit);
|
||||
if(err != noErr)
|
||||
return -1;
|
||||
|
||||
//Start the rendering
|
||||
//The DefaultOutputUnit will do any format conversions to the format of the default device
|
||||
err = AudioOutputUnitStart(output_unit);
|
||||
if(err != noErr)
|
||||
return -1;
|
||||
|
||||
//
|
||||
current_volume_scalar = 100;
|
||||
|
||||
//we call the CFRunLoopRunInMode to service any notifications that the audio
|
||||
//system has to deal with
|
||||
//CFRunLoopRunInMode(kCFRunLoopDefaultMode, 2, false);
|
||||
//verify_noerr (AudioOutputUnitStop (output_unit));
|
||||
|
||||
mix_sound = true;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SNDOSXDeInit()
|
||||
{
|
||||
if(output_unit != NULL)
|
||||
{
|
||||
//wait for mix to end
|
||||
mix_sound = false;
|
||||
while(in_mix);
|
||||
|
||||
//closes the audio unit (errors are ignored here)
|
||||
AudioOutputUnitStop(output_unit);
|
||||
AudioUnitUninitialize(output_unit);
|
||||
|
||||
output_unit = NULL;
|
||||
}
|
||||
|
||||
SNDOSXCloseFile(); //end recording to file if needed
|
||||
|
||||
if(sound_data != NULL)
|
||||
{
|
||||
free(sound_data);
|
||||
sound_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int SNDOSXReset()
|
||||
{
|
||||
if(sound_data == NULL)return;
|
||||
|
||||
memset(sound_data, 0, sound_buffer_size);
|
||||
|
||||
sound_offset = 0;
|
||||
sound_position = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SNDOSXUpdateAudio(s16 *buffer, u32 num_samples)
|
||||
{
|
||||
//printf("NEW SOUND DATA %u ", num_samples * SAMPLE_SIZE);
|
||||
|
||||
if(sound_data == NULL)return;
|
||||
|
||||
//get the avilable bufferspace ------------------------------------------------
|
||||
|
||||
//in these calculatations:
|
||||
//1 is subtracted from sound_buffer_size since if the size is 2, we can only go to index 1
|
||||
//1 is subtracted from sound_position since sound_offset should never catch up to it
|
||||
//since them being equal means that the buffer is empty, rather than full
|
||||
|
||||
u32 bytes_to_copy = num_samples * SAMPLE_SIZE;
|
||||
|
||||
int sound_pos = sound_position; //incase the sound render thread changes it
|
||||
|
||||
u32 copy1size, copy2size;
|
||||
|
||||
if(sound_offset >= sound_pos)
|
||||
{
|
||||
if(sound_pos > 0)
|
||||
{
|
||||
copy1size = sound_buffer_size - sound_offset;
|
||||
copy2size = (sound_pos-1);
|
||||
} else
|
||||
{
|
||||
copy1size = sound_buffer_size - sound_offset - 1;
|
||||
copy2size = 0;
|
||||
}
|
||||
} else if(sound_offset < sound_pos)
|
||||
{
|
||||
copy1size = sound_pos - sound_offset - 1;
|
||||
copy2size = 0;
|
||||
}
|
||||
|
||||
//printf("copy1:%u copy2:%u both:%u\n",copy1size, copy2size, copy2size+copy1size);
|
||||
//truncate the copy sizes to however much we've been been given to fill --------
|
||||
|
||||
if(copy1size + copy2size < bytes_to_copy)
|
||||
//this shouldn't happen as the emulator core generally asks how much
|
||||
//space is available before sending stuff, but just incase
|
||||
printf("NDOSXUpdateAudio() error: not enough space in buffer");
|
||||
else
|
||||
{
|
||||
u32 diff = copy1size + copy2size - bytes_to_copy;
|
||||
|
||||
if(diff <= copy2size)
|
||||
{
|
||||
copy2size -= diff;
|
||||
} else
|
||||
{
|
||||
diff -= copy2size;
|
||||
copy2size = 0;
|
||||
copy1size -= diff;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//copy the data -------------------------------------------------------------
|
||||
|
||||
memcpy((((u8 *)sound_data)+sound_offset), buffer, copy1size);
|
||||
|
||||
if(copy2size)
|
||||
memcpy(sound_data, ((u8 *)buffer)+copy1size, copy2size);
|
||||
|
||||
//change our sound_offset
|
||||
sound_offset += copy1size + copy2size;
|
||||
while(sound_offset >= sound_buffer_size)sound_offset -= sound_buffer_size;
|
||||
|
||||
//printf("cop1%u cop2%u off%u size%u \n", copy1size, copy2size, sound_offset, sound_buffer_size);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
u32 SNDOSXGetAudioSpace()
|
||||
{
|
||||
if(sound_data == NULL)return 0;
|
||||
|
||||
int sound_pos = sound_position; //incase the sound render thread changes it
|
||||
|
||||
u32 free_space;
|
||||
|
||||
if(sound_offset > sound_pos)
|
||||
free_space = sound_buffer_size + sound_pos - 1 - sound_offset;
|
||||
else if(sound_offset < sound_pos)
|
||||
free_space = sound_pos - sound_offset - 1;
|
||||
else
|
||||
free_space = sound_buffer_size-1; //sound_offset == sound_data, meaning the buffer is empty
|
||||
|
||||
return (free_space / SAMPLE_SIZE);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SNDOSXMuteAudio()
|
||||
{
|
||||
if(sound_data == NULL)return;
|
||||
|
||||
OSStatus err = AudioUnitSetParameter(output_unit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, 0, 0);
|
||||
|
||||
if(err != noErr)
|
||||
printf("SNDOSXMuteAudio error\n");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SNDOSXUnMuteAudio()
|
||||
{
|
||||
if(sound_data == NULL)return;
|
||||
|
||||
OSStatus err = AudioUnitSetParameter(output_unit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, current_volume_scalar, 0);
|
||||
|
||||
if(err != noErr)
|
||||
printf("SNDOSXUnMuteAudio %f error\n",current_volume_scalar);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SNDOSXSetVolume(int volume)
|
||||
{
|
||||
if(sound_data == NULL)return;
|
||||
|
||||
if(volume > 100)volume = 100;
|
||||
if(volume < 0)volume = 0;
|
||||
|
||||
current_volume_scalar = volume;
|
||||
current_volume_scalar /= 100.0;
|
||||
|
||||
OSStatus err = AudioUnitSetParameter(output_unit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, current_volume_scalar, 0);
|
||||
|
||||
if(err != noErr)
|
||||
printf("SNDOSXSetVolume %f error\n",current_volume_scalar);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SoundInterface_struct SNDOSX = {
|
||||
SNDCORE_OSX,
|
||||
"Core Audio Sound Interface",
|
||||
SNDOSXInit,
|
||||
SNDOSXDeInit,
|
||||
SNDOSXUpdateAudio,
|
||||
SNDOSXGetAudioSpace,
|
||||
SNDOSXMuteAudio,
|
||||
SNDOSXUnMuteAudio,
|
||||
SNDOSXSetVolume
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//Sound recording
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool SNDOSXOpenFile(void *fname)
|
||||
{
|
||||
if(sound_data == NULL)return false;
|
||||
|
||||
SNDOSXCloseFile();
|
||||
|
||||
if(!fname)return false;
|
||||
|
||||
NSString *filename = (NSString*)fname;
|
||||
FSRef ref;
|
||||
|
||||
if(FSPathMakeRef((const UInt8*)[[filename stringByDeletingLastPathComponent] fileSystemRepresentation], &ref, NULL) != noErr)
|
||||
{
|
||||
SNDOSXStopRecording();
|
||||
return false;
|
||||
}
|
||||
|
||||
AudioStreamBasicDescription audio_format;
|
||||
audio_format.mSampleRate = 44100;
|
||||
audio_format.mFormatID = kAudioFormatLinearPCM;
|
||||
audio_format.mFormatFlags = kAudioFormatFlagIsSignedInteger
|
||||
| kAudioFormatFlagsNativeEndian
|
||||
| kLinearPCMFormatFlagIsPacked;
|
||||
audio_format.mBytesPerPacket = 4;
|
||||
audio_format.mFramesPerPacket = 1;
|
||||
audio_format.mBytesPerFrame = 4;
|
||||
audio_format.mChannelsPerFrame = 2;
|
||||
audio_format.mBitsPerChannel = 16;
|
||||
|
||||
if(ExtAudioFileCreateNew(&ref, (CFStringRef)[[filename pathComponents] lastObject], kAudioFileWAVEType, &audio_format, NULL, &outfile) != noErr)
|
||||
return false;
|
||||
|
||||
file_open = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SNDOSXStartRecording()
|
||||
{
|
||||
if(sound_data == NULL)return;
|
||||
}
|
||||
|
||||
void SNDOSXStopRecording()
|
||||
{
|
||||
if(sound_data == NULL)return;
|
||||
}
|
||||
|
||||
void SNDOSXCloseFile()
|
||||
{
|
||||
if(sound_data == NULL)return;
|
||||
|
||||
if(file_open)
|
||||
{
|
||||
file_open = false;
|
||||
|
||||
//if it's rendering sound, wait until it's not
|
||||
//so we dont close the file while writing to it
|
||||
while(in_mix);
|
||||
|
||||
ExtAudioFileDispose(outfile);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
Loading…
Reference in New Issue