This commit is contained in:
Miodrag Milanovic 2015-04-08 14:02:30 +02:00
commit 9cc6018c15
6 changed files with 308 additions and 71 deletions

View File

@ -40,7 +40,7 @@ static ADDRESS_MAP_START( main_map, AS_PROGRAM, 16, tail2nos_state )
AM_RANGE(0xff8000, 0xffbfff) AM_RAM /* work RAM */ AM_RANGE(0xff8000, 0xffbfff) AM_RAM /* work RAM */
AM_RANGE(0xffc000, 0xffc2ff) AM_RAM AM_SHARE("spriteram") AM_RANGE(0xffc000, 0xffc2ff) AM_RAM AM_SHARE("spriteram")
AM_RANGE(0xffc300, 0xffcfff) AM_RAM AM_RANGE(0xffc300, 0xffcfff) AM_RAM
AM_RANGE(0xffd000, 0xffdfff) AM_RAM_WRITE(tail2nos_bgvideoram_w) AM_SHARE("bgvideoram") AM_RANGE(0xffd000, 0xffdfff) AM_RAM_WRITE(tail2nos_txvideoram_w) AM_SHARE("txvideoram")
AM_RANGE(0xffe000, 0xffefff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette") AM_RANGE(0xffe000, 0xffefff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
AM_RANGE(0xfff000, 0xfff001) AM_READ_PORT("INPUTS") AM_WRITE(tail2nos_gfxbank_w) AM_RANGE(0xfff000, 0xfff001) AM_READ_PORT("INPUTS") AM_WRITE(tail2nos_gfxbank_w)
AM_RANGE(0xfff004, 0xfff005) AM_READ_PORT("DSW") AM_RANGE(0xfff004, 0xfff005) AM_READ_PORT("DSW")
@ -187,15 +187,15 @@ void tail2nos_state::machine_start()
membank("bank3")->configure_entries(0, 2, &ROM[0x10000], 0x8000); membank("bank3")->configure_entries(0, 2, &ROM[0x10000], 0x8000);
membank("bank3")->set_entry(0); membank("bank3")->set_entry(0);
save_item(NAME(m_charbank)); save_item(NAME(m_txbank));
save_item(NAME(m_charpalette)); save_item(NAME(m_txpalette));
save_item(NAME(m_video_enable)); save_item(NAME(m_video_enable));
} }
void tail2nos_state::machine_reset() void tail2nos_state::machine_reset()
{ {
m_charbank = 0; m_txbank = 0;
m_charpalette = 0; m_txpalette = 0;
m_video_enable = 0; m_video_enable = 0;
} }
@ -301,7 +301,7 @@ ROM_START( sformula )
ROM_LOAD( "a24", 0x00000, 0x80000, CRC(b1e9de43) SHA1(0144252dd9ed561fbebd4994cccf11f6c87e1825) ) ROM_LOAD( "a24", 0x00000, 0x80000, CRC(b1e9de43) SHA1(0144252dd9ed561fbebd4994cccf11f6c87e1825) )
ROM_LOAD( "o1s", 0x80000, 0x40000, CRC(e27a8eb4) SHA1(4fcadabf42a1c3deeb6d74d75cdbee802cf16db5) ) ROM_LOAD( "o1s", 0x80000, 0x40000, CRC(e27a8eb4) SHA1(4fcadabf42a1c3deeb6d74d75cdbee802cf16db5) )
ROM_REGION( 0x080000, "gfx2", 0 ) ROM_REGION( 0x80000, "gfx2", 0 )
ROM_LOAD( "oj1", 0x000000, 0x40000, CRC(39c36b35) SHA1(a97480696bf6d81bf415737e03cc5324d439ab84) ) ROM_LOAD( "oj1", 0x000000, 0x40000, CRC(39c36b35) SHA1(a97480696bf6d81bf415737e03cc5324d439ab84) )
ROM_LOAD( "oj2", 0x040000, 0x40000, CRC(77ccaea2) SHA1(e38175859c75c6d0f2f01752fad6e167608c4662) ) ROM_LOAD( "oj2", 0x040000, 0x40000, CRC(77ccaea2) SHA1(e38175859c75c6d0f2f01752fad6e167608c4662) )
@ -310,5 +310,39 @@ ROM_START( sformula )
ROM_END ROM_END
ROM_START( sformulaa )
ROM_REGION( 0x40000, "maincpu", 0 ) /* 68000 code */
ROM_LOAD16_BYTE( "04.bin", 0x00000, 0x10000, CRC(f40e9c3c) SHA1(2ab45f46f92bce42748692cafe601c5893de127b) )
ROM_LOAD16_BYTE( "07.bin", 0x00001, 0x10000, CRC(d1cf6dca) SHA1(18228cc98722eb5907850e2d0317d1f4bf04fb8f) )
ROM_LOAD16_BYTE( "v3", 0x20000, 0x10000, CRC(e2e0abad) SHA1(1a1054bada9654484fe81fe4b4b32af5ab7b53f0) )
ROM_LOAD16_BYTE( "v6", 0x20001, 0x10000, CRC(069817a7) SHA1(cca382fe2a49c8c3c84b879a1c30dffff84ef406) )
ROM_REGION16_BE( 0x80000, "user1", 0 )
/* extra ROM mapped at 200000 */
ROM_LOAD16_WORD_SWAP( "a23", 0x00000, 0x80000, CRC(d851cf04) SHA1(ac5b366b686c5a037b127d223dc6fe90985eb160) )
ROM_REGION16_BE( 0x20000, "user2", 0 )
/* extra ROM mapped at 2c0000 */
ROM_LOAD16_BYTE( "v5", 0x00000, 0x10000, CRC(a9fe15a1) SHA1(d90bf40c610ea7daaa338f83f82cdffbae7da08e) )
ROM_LOAD16_BYTE( "v8", 0x00001, 0x10000, CRC(4fb6a43e) SHA1(5cddda0029b3b141c88b0c128655d35bb12fa34d) )
ROM_REGION( 0x20000, "audiocpu", 0 ) /* 64k for the audio CPU + banks */
ROM_LOAD( "v2", 0x00000, 0x08000, CRC(920d8920) SHA1(b8d30903248fee6f985af7fafbe534cfc8c6e829) )
ROM_LOAD( "v1", 0x10000, 0x10000, CRC(bf35c1a4) SHA1(a838740e023dc3344dc528324a8dbc48bb98b574) )
ROM_REGION( 0x100000, "gfx1", ROMREGION_ERASE00 )
ROM_LOAD( "a24", 0x00000, 0x80000, CRC(b1e9de43) SHA1(0144252dd9ed561fbebd4994cccf11f6c87e1825) )
ROM_LOAD( "o1s", 0x80000, 0x40000, CRC(e27a8eb4) SHA1(4fcadabf42a1c3deeb6d74d75cdbee802cf16db5) )
ROM_LOAD( "9.bin", 0xc0000, 0x08000, CRC(c76edc0a) SHA1(2c6c21f8d1f3bcb0f65ba5a779fe479783271e0b) ) // present on this PCB, contains Japanese text + same font as in above roms, where does it map? is there another layer?
ROM_REGION( 0x80000, "gfx2", 0 )
ROM_LOAD( "oj1", 0x000000, 0x40000, CRC(39c36b35) SHA1(a97480696bf6d81bf415737e03cc5324d439ab84) )
ROM_LOAD( "oj2", 0x040000, 0x40000, CRC(77ccaea2) SHA1(e38175859c75c6d0f2f01752fad6e167608c4662) )
ROM_REGION( 0x20000, "ymsnd", 0 ) /* sound samples */
ROM_LOAD( "osb", 0x00000, 0x20000, CRC(d49ab2f5) SHA1(92f7f6c8f35ac39910879dd88d2cfb6db7c848c9) )
ROM_END
GAME( 1989, tail2nos, 0, tail2nos, tail2nos, driver_device, 0, ROT90, "V-System Co.", "Tail to Nose - Great Championship", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) GAME( 1989, tail2nos, 0, tail2nos, tail2nos, driver_device, 0, ROT90, "V-System Co.", "Tail to Nose - Great Championship", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE )
GAME( 1989, sformula, tail2nos, tail2nos, tail2nos, driver_device, 0, ROT90, "V-System Co.", "Super Formula (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) GAME( 1989, sformula, tail2nos, tail2nos, tail2nos, driver_device, 0, ROT90, "V-System Co.", "Super Formula (Japan, set 1)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE )
GAME( 1989, sformulaa,tail2nos, tail2nos, tail2nos, driver_device, 0, ROT90, "V-System Co.", "Super Formula (Japan, set 2)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) // No Japan warning, but Japanese version

View File

@ -11,7 +11,7 @@ class tail2nos_state : public driver_device
public: public:
tail2nos_state(const machine_config &mconfig, device_type type, const char *tag) tail2nos_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag), : driver_device(mconfig, type, tag),
m_bgvideoram(*this, "bgvideoram"), m_txvideoram(*this, "txvideoram"),
m_spriteram(*this, "spriteram"), m_spriteram(*this, "spriteram"),
m_zoomram(*this, "k051316"), m_zoomram(*this, "k051316"),
m_maincpu(*this, "maincpu"), m_maincpu(*this, "maincpu"),
@ -21,14 +21,14 @@ public:
m_palette(*this, "palette") { } m_palette(*this, "palette") { }
/* memory pointers */ /* memory pointers */
required_shared_ptr<UINT16> m_bgvideoram; required_shared_ptr<UINT16> m_txvideoram;
required_shared_ptr<UINT16> m_spriteram; required_shared_ptr<UINT16> m_spriteram;
required_shared_ptr<UINT16> m_zoomram; required_shared_ptr<UINT16> m_zoomram;
/* video-related */ /* video-related */
tilemap_t *m_bg_tilemap; tilemap_t *m_tx_tilemap;
int m_charbank; int m_txbank;
int m_charpalette; int m_txpalette;
int m_video_enable; int m_video_enable;
/* devices */ /* devices */
@ -39,7 +39,7 @@ public:
required_device<palette_device> m_palette; required_device<palette_device> m_palette;
DECLARE_WRITE16_MEMBER(sound_command_w); DECLARE_WRITE16_MEMBER(sound_command_w);
DECLARE_WRITE16_MEMBER(tail2nos_bgvideoram_w); DECLARE_WRITE16_MEMBER(tail2nos_txvideoram_w);
DECLARE_WRITE16_MEMBER(tail2nos_zoomdata_w); DECLARE_WRITE16_MEMBER(tail2nos_zoomdata_w);
DECLARE_WRITE16_MEMBER(tail2nos_gfxbank_w); DECLARE_WRITE16_MEMBER(tail2nos_gfxbank_w);
DECLARE_WRITE8_MEMBER(sound_bankswitch_w); DECLARE_WRITE8_MEMBER(sound_bankswitch_w);

View File

@ -8717,6 +8717,7 @@ svolleyu // (c) 1989 V-System Co. + Data East license (US)
svolleybl // bootleg svolleybl // bootleg
tail2nos // [1989] V-System Co. tail2nos // [1989] V-System Co.
sformula // [1989] V-System Co. (Japan) sformula // [1989] V-System Co. (Japan)
sformulaa // [1989] V-System Co. (Japan)
ojankoc // [1986] V-System Co. (Japan) ojankoc // [1986] V-System Co. (Japan)
ojankoy // [1986] V-System Co. (Japan) ojankoy // [1986] V-System Co. (Japan)
ojanko2 // [1987] V-System Co. (Japan) ojanko2 // [1987] V-System Co. (Japan)

View File

@ -12,10 +12,10 @@
TILE_GET_INFO_MEMBER(tail2nos_state::get_tile_info) TILE_GET_INFO_MEMBER(tail2nos_state::get_tile_info)
{ {
UINT16 code = m_bgvideoram[tile_index]; UINT16 code = m_txvideoram[tile_index];
SET_TILE_INFO_MEMBER(0, SET_TILE_INFO_MEMBER(0,
(code & 0x1fff) + (m_charbank << 13), (code & 0x1fff) + (m_txbank << 13),
((code & 0xe000) >> 13) + m_charpalette * 16, ((code & 0xe000) >> 13) + m_txpalette * 16,
0); 0);
} }
@ -40,16 +40,16 @@ K051316_CB_MEMBER(tail2nos_state::zoom_callback)
void tail2nos_state::tail2nos_postload() void tail2nos_state::tail2nos_postload()
{ {
m_bg_tilemap->mark_all_dirty(); m_tx_tilemap->mark_all_dirty();
m_k051316->gfx(0)->mark_all_dirty(); m_k051316->gfx(0)->mark_all_dirty();
} }
void tail2nos_state::video_start() void tail2nos_state::video_start()
{ {
m_bg_tilemap = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(tail2nos_state::get_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); m_tx_tilemap = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(tail2nos_state::get_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
m_bg_tilemap->set_transparent_pen(15); m_tx_tilemap->set_transparent_pen(15);
machine().save().register_postload(save_prepost_delegate(FUNC(tail2nos_state::tail2nos_postload), this)); machine().save().register_postload(save_prepost_delegate(FUNC(tail2nos_state::tail2nos_postload), this));
} }
@ -62,10 +62,10 @@ void tail2nos_state::video_start()
***************************************************************************/ ***************************************************************************/
WRITE16_MEMBER(tail2nos_state::tail2nos_bgvideoram_w) WRITE16_MEMBER(tail2nos_state::tail2nos_txvideoram_w)
{ {
COMBINE_DATA(&m_bgvideoram[offset]); COMBINE_DATA(&m_txvideoram[offset]);
m_bg_tilemap->mark_tile_dirty(offset); m_tx_tilemap->mark_tile_dirty(offset);
} }
WRITE16_MEMBER(tail2nos_state::tail2nos_zoomdata_w) WRITE16_MEMBER(tail2nos_state::tail2nos_zoomdata_w)
@ -79,22 +79,24 @@ WRITE16_MEMBER(tail2nos_state::tail2nos_zoomdata_w)
WRITE16_MEMBER(tail2nos_state::tail2nos_gfxbank_w) WRITE16_MEMBER(tail2nos_state::tail2nos_gfxbank_w)
{ {
// -------- --pe-b-b
// p = palette bank
// b = tile bank
// e = video enable
if (ACCESSING_BITS_0_7) if (ACCESSING_BITS_0_7)
{ {
int bank; int bank;
bank = 0;
/* bits 0 and 2 select char bank */ /* bits 0 and 2 select char bank */
if (data & 0x04) if (data & 0x04) bank |= 2;
bank = 2; if (data & 0x01) bank |= 1;
else if (data & 0x01)
bank = 1;
else
bank = 0;
if (m_charbank != bank)
if (m_txbank != bank)
{ {
m_charbank = bank; m_txbank = bank;
m_bg_tilemap->mark_all_dirty(); m_tx_tilemap->mark_all_dirty();
} }
/* bit 5 seems to select palette bank (used on startup) */ /* bit 5 seems to select palette bank (used on startup) */
@ -103,10 +105,10 @@ WRITE16_MEMBER(tail2nos_state::tail2nos_gfxbank_w)
else else
bank = 3; bank = 3;
if (m_charpalette != bank) if (m_txpalette != bank)
{ {
m_charpalette = bank; m_txpalette = bank;
m_bg_tilemap->mark_all_dirty(); m_tx_tilemap->mark_all_dirty();
} }
/* bit 4 seems to be video enable */ /* bit 4 seems to be video enable */
@ -157,7 +159,7 @@ UINT32 tail2nos_state::screen_update_tail2nos(screen_device &screen, bitmap_ind1
{ {
m_k051316->zoom_draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE, 0); m_k051316->zoom_draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE, 0);
draw_sprites(bitmap, cliprect); draw_sprites(bitmap, cliprect);
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
} }
else else
bitmap.fill(0, cliprect); bitmap.fill(0, cliprect);

View File

@ -543,13 +543,13 @@ bool sound_coreaudio::extract_effect_info(
manufacturer_val = CFDictionaryGetValue(desc, CFSTR("ComponentManufacturer")); manufacturer_val = CFDictionaryGetValue(desc, CFSTR("ComponentManufacturer"));
class_info = CFDictionaryGetValue(desc, CFSTR("ClassInfo")); class_info = CFDictionaryGetValue(desc, CFSTR("ClassInfo"));
} }
else if (CFDictionaryContainsKey(desc, CFSTR("type")) else if (CFDictionaryContainsKey(desc, CFSTR(kAUPresetTypeKey))
&& CFDictionaryContainsKey(desc, CFSTR("subtype")) && CFDictionaryContainsKey(desc, CFSTR(kAUPresetSubtypeKey))
&& CFDictionaryContainsKey(desc, CFSTR("manufacturer"))) && CFDictionaryContainsKey(desc, CFSTR(kAUPresetManufacturerKey)))
{ {
type_val = CFDictionaryGetValue(desc, CFSTR("type")); type_val = CFDictionaryGetValue(desc, CFSTR(kAUPresetTypeKey));
subtype_val = CFDictionaryGetValue(desc, CFSTR("subtype")); subtype_val = CFDictionaryGetValue(desc, CFSTR(kAUPresetSubtypeKey));
manufacturer_val = CFDictionaryGetValue(desc, CFSTR("manufacturer")); manufacturer_val = CFDictionaryGetValue(desc, CFSTR(kAUPresetManufacturerKey));
class_info = properties; class_info = properties;
} }
else else

View File

@ -44,6 +44,8 @@ static NSString *const ComponentTypeKey = @"ComponentType";
static NSString *const ComponentSubTypeKey = @"ComponentSubType"; static NSString *const ComponentSubTypeKey = @"ComponentSubType";
static NSString *const ComponentManufacturerKey = @"ComponentManufacturer"; static NSString *const ComponentManufacturerKey = @"ComponentManufacturer";
static NSString *const ClassInfoKey = @"ClassInfo"; static NSString *const ClassInfoKey = @"ClassInfo";
static NSString *const ForceGenericViewKey = @"ForceGenericView";
static NSString *const WindowFrameKey = @"WindowFrame";
static void UpdateChangeCountCallback(void *userData, static void UpdateChangeCountCallback(void *userData,
@ -59,8 +61,14 @@ static void UpdateChangeCountCallback(void *userData,
@interface AUEffectDocument : NSDocument <NSWindowDelegate> @interface AUEffectDocument : NSDocument <NSWindowDelegate>
{ {
IBOutlet NSWindow *window; IBOutlet NSWindow *window;
IBOutlet NSButton *genericViewButton;
IBOutlet NSPopUpButton *presetButton;
NSView *view; NSView *view;
NSSize headerSize;
CFArrayRef presets;
AUParameterListenerRef listener; AUParameterListenerRef listener;
BOOL forceGenericView;
NSString *restoreFrame;
AudioComponentDescription description; AudioComponentDescription description;
AUGraph graph; AUGraph graph;
@ -74,6 +82,9 @@ static void UpdateChangeCountCallback(void *userData,
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)type error:(NSError **)error; - (BOOL)readFromData:(NSData *)data ofType:(NSString *)type error:(NSError **)error;
- (NSData *)dataOfType:(NSString *)type error:(NSError **)error; - (NSData *)dataOfType:(NSString *)type error:(NSError **)error;
- (IBAction)toggleGenericView:(id)sender;
- (IBAction)loadPreset:(id)sender;
- (void)viewFrameDidChange:(NSNotification *)notification; - (void)viewFrameDidChange:(NSNotification *)notification;
@end @end
@ -84,6 +95,7 @@ static void UpdateChangeCountCallback(void *userData,
if ((0 == effectNode) || (nil == window)) if ((0 == effectNode) || (nil == window))
return; return;
BOOL customViewValid = NO;
OSStatus status; OSStatus status;
UInt32 uiDescSize; UInt32 uiDescSize;
AudioUnitCocoaViewInfo *viewInfo; AudioUnitCocoaViewInfo *viewInfo;
@ -111,10 +123,14 @@ static void UpdateChangeCountCallback(void *userData,
&& [viewClass conformsToProtocol:@protocol(AUCocoaUIBase)] && [viewClass conformsToProtocol:@protocol(AUCocoaUIBase)]
&& [viewClass instancesRespondToSelector:@selector(uiViewForAudioUnit:withSize:)]) && [viewClass instancesRespondToSelector:@selector(uiViewForAudioUnit:withSize:)])
{ {
id const factory = [[viewClass alloc] init]; customViewValid = YES;
view = [factory uiViewForAudioUnit:effectUnit if (!forceGenericView)
withSize:[[window contentView] bounds].size]; {
[factory release]; id const factory = [[viewClass alloc] init];
view = [factory uiViewForAudioUnit:effectUnit
withSize:[[window contentView] bounds].size];
[factory release];
}
} }
CFRelease(viewInfo->mCocoaAUViewBundleLocation); CFRelease(viewInfo->mCocoaAUViewBundleLocation);
for (UInt32 i = 0; i < uiClassCount; i++) for (UInt32 i = 0; i < uiClassCount; i++)
@ -133,9 +149,9 @@ static void UpdateChangeCountCallback(void *userData,
NSRect const oldFrame = [window frame]; NSRect const oldFrame = [window frame];
NSRect const desired = [window frameRectForContentRect:[view frame]]; NSRect const desired = [window frameRectForContentRect:[view frame]];
NSRect const newFrame = NSMakeRect(oldFrame.origin.x, NSRect const newFrame = NSMakeRect(oldFrame.origin.x,
oldFrame.origin.y + oldFrame.size.height - desired.size.height, oldFrame.origin.y + oldFrame.size.height - headerSize.height - desired.size.height,
desired.size.width, desired.size.width,
desired.size.height); headerSize.height + desired.size.height);
[window setFrame:newFrame display:YES animate:NO]; [window setFrame:newFrame display:YES animate:NO];
[[window contentView] addSubview:view]; [[window contentView] addSubview:view];
[view setPostsFrameChangedNotifications:YES]; [view setPostsFrameChangedNotifications:YES];
@ -143,22 +159,56 @@ static void UpdateChangeCountCallback(void *userData,
selector:@selector(viewFrameDidChange:) selector:@selector(viewFrameDidChange:)
name:NSViewFrameDidChangeNotification name:NSViewFrameDidChangeNotification
object:view]; object:view];
[genericViewButton setEnabled:customViewValid];
if (!customViewValid)
{
forceGenericView = YES;
[genericViewButton setState:NSOnState];
}
CFIndex const presetCount = (NULL != presets) ? CFArrayGetCount(presets) : 0;
[presetButton setEnabled:(0 < presetCount)];
while (1 < [presetButton numberOfItems])
[presetButton removeItemAtIndex:1];
for (CFIndex i = 0; i < presetCount; i++)
{
AUPreset const *preset = (AUPreset const*)CFArrayGetValueAtIndex(presets, i);
NSMenuItem const *item = [[presetButton menu] addItemWithTitle:(NSString *)preset->presetName
action:@selector(loadPreset:)
keyEquivalent:@""];
[item setTarget:self];
[item setTag:i];
}
} }
- (id)init { - (id)init {
if (!(self = [super init])) return nil; if (!(self = [super init])) return nil;
window = nil; window = nil;
genericViewButton = nil;
presetButton = nil;
view = nil; view = nil;
presets = NULL;
listener = NULL; listener = NULL;
forceGenericView = NO;
restoreFrame = nil;
description.componentType = description.componentSubType = description.componentManufacturer = 0; description.componentType = description.componentSubType = description.componentManufacturer = 0;
description.componentFlags = description.componentFlagsMask = 0; description.componentFlags = description.componentFlagsMask = 0;
graph = NULL; graph = NULL;
outputNode = sourceNode = effectNode = 0; outputNode = sourceNode = effectNode = 0;
AudioComponentDescription const outputDesc = { kAudioUnitType_Output, kAudioUnitSubType_DefaultOutput, kAudioUnitManufacturer_Apple, 0, 0, }; AudioComponentDescription const outputDesc = { kAudioUnitType_Output,
AudioComponentDescription const sourceDesc = { kAudioUnitType_Generator, kAudioUnitSubType_AudioFilePlayer, kAudioUnitManufacturer_Apple, 0, 0, }; kAudioUnitSubType_DefaultOutput,
kAudioUnitManufacturer_Apple,
0,
0, };
AudioComponentDescription const sourceDesc = { kAudioUnitType_Generator,
kAudioUnitSubType_AudioFilePlayer,
kAudioUnitManufacturer_Apple,
0,
0, };
if ((noErr != NewAUGraph(&graph)) if ((noErr != NewAUGraph(&graph))
|| (noErr != AUGraphAddNode(graph, &outputDesc, &outputNode)) || (noErr != AUGraphAddNode(graph, &outputDesc, &outputNode))
|| (noErr != AUGraphAddNode(graph, &sourceDesc, &sourceNode)) || (noErr != AUGraphAddNode(graph, &sourceDesc, &sourceNode))
@ -175,9 +225,15 @@ static void UpdateChangeCountCallback(void *userData,
} }
- (void)dealloc { - (void)dealloc {
if (NULL != presets)
CFRelease(presets);
if (NULL != listener) if (NULL != listener)
AUListenerDispose(listener); AUListenerDispose(listener);
if (nil != restoreFrame)
[restoreFrame release];
if (NULL != graph) if (NULL != graph)
{ {
AUGraphClose(graph); AUGraphClose(graph);
@ -188,16 +244,57 @@ static void UpdateChangeCountCallback(void *userData,
} }
- (void)makeWindowControllers { - (void)makeWindowControllers {
window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 400, 300) genericViewButton = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 18)];
[genericViewButton setAutoresizingMask:NSViewNotSizable];
[[genericViewButton cell] setControlSize:NSSmallControlSize];
[genericViewButton setButtonType:NSSwitchButton];
[genericViewButton setBordered:NO];
[genericViewButton setAllowsMixedState:NO];
[genericViewButton setState:(forceGenericView ? NSOnState : NSOffState)];
[genericViewButton setTitle:@"Use generic editor view"];
[genericViewButton setAction:@selector(toggleGenericView:)];
[genericViewButton setTarget:self];
[genericViewButton sizeToFit];
presetButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 22) pullsDown:YES];
[presetButton setAutoresizingMask:NSViewNotSizable];
[[presetButton cell] setControlSize:NSSmallControlSize];
[[presetButton cell] setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]];
[presetButton setTitle:@"Load preset"];
[[[presetButton menu] addItemWithTitle:@"Load preset" action:NULL keyEquivalent:@""] setHidden:YES];
[presetButton sizeToFit];
CGFloat const controlWidth = MAX(NSWidth([genericViewButton frame]), NSWidth([presetButton frame]));
NSRect const presetFrame = NSMakeRect(17,
8,
controlWidth,
NSHeight([presetButton frame]));
NSRect const genericViewFrame = NSMakeRect(17,
NSMaxY(presetFrame) + 9,
controlWidth,
NSHeight([genericViewButton frame]));
[genericViewButton setFrame:genericViewFrame];
[presetButton setFrame:presetFrame];
headerSize = NSMakeSize((2 * 17) + controlWidth, 18 + NSMaxY(genericViewFrame));
NSView *const container = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, headerSize.width, headerSize.height)];
[container setAutoresizingMask:(NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin)];
[container addSubview:genericViewButton];
[genericViewButton release];
[container addSubview:presetButton];
[presetButton release];
window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, headerSize.width, headerSize.height)
styleMask:(NSTitledWindowMask | styleMask:(NSTitledWindowMask |
NSClosableWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask) NSMiniaturizableWindowMask)
backing:NSBackingStoreBuffered backing:NSBackingStoreBuffered
defer:YES]; defer:YES];
[window setContentMinSize:NSMakeSize(400, 300)];
[window setReleasedWhenClosed:NO]; [window setReleasedWhenClosed:NO];
[window setDelegate:self]; [window setDelegate:self];
[window setTitle:@"Effect"]; [window setTitle:@"Effect"];
[[window contentView] addSubview:container];
[container release];
[self setWindow:window]; [self setWindow:window];
NSWindowController *const controller = [[NSWindowController alloc] initWithWindow:window]; NSWindowController *const controller = [[NSWindowController alloc] initWithWindow:window];
@ -206,10 +303,13 @@ static void UpdateChangeCountCallback(void *userData,
[window release]; [window release];
[self loadEffectUI]; [self loadEffectUI];
if (nil != restoreFrame)
[window setFrameFromString:restoreFrame];
} }
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)type error:(NSError **)error { - (BOOL)readFromData:(NSData *)data ofType:(NSString *)type error:(NSError **)error {
OSStatus status; OSStatus status;
UInt32 propertySize;
BOOL const hasWrapper = [type isEqualToString:AUEffectDocumentType]; BOOL const hasWrapper = [type isEqualToString:AUEffectDocumentType];
if (!hasWrapper && ![type isEqualToString:AUPresetDocumentType]) if (!hasWrapper && ![type isEqualToString:AUPresetDocumentType])
@ -243,9 +343,9 @@ static void UpdateChangeCountCallback(void *userData,
return NO; return NO;
} }
id const typeValue = [desc objectForKey:(hasWrapper ? ComponentTypeKey : @"type")]; id const typeValue = [desc objectForKey:(hasWrapper ? ComponentTypeKey : (NSString *)CFSTR(kAUPresetTypeKey))];
id const subtypeValue = [desc objectForKey:(hasWrapper ? ComponentSubTypeKey : @"subtype")]; id const subtypeValue = [desc objectForKey:(hasWrapper ? ComponentSubTypeKey : (NSString *)CFSTR(kAUPresetSubtypeKey))];
id const manufacturerValue = [desc objectForKey:(hasWrapper ? ComponentManufacturerKey : @"manufacturer")]; id const manufacturerValue = [desc objectForKey:(hasWrapper ? ComponentManufacturerKey : (NSString *)CFSTR(kAUPresetManufacturerKey))];
if ((nil == typeValue) || ![typeValue isKindOfClass:[NSNumber class]] if ((nil == typeValue) || ![typeValue isKindOfClass:[NSNumber class]]
|| (nil == subtypeValue) || ![subtypeValue isKindOfClass:[NSNumber class]] || (nil == subtypeValue) || ![subtypeValue isKindOfClass:[NSNumber class]]
|| (nil == manufacturerValue) || ![manufacturerValue isKindOfClass:[NSNumber class]] || (nil == manufacturerValue) || ![manufacturerValue isKindOfClass:[NSNumber class]]
@ -261,6 +361,11 @@ static void UpdateChangeCountCallback(void *userData,
return NO; return NO;
} }
if (NULL != presets)
{
CFRelease(presets);
presets = NULL;
}
if (NULL != listener) if (NULL != listener)
{ {
AUListenerDispose(listener); AUListenerDispose(listener);
@ -331,13 +436,14 @@ static void UpdateChangeCountCallback(void *userData,
} }
} }
UInt32 paramListSize = 0; propertySize = 0;
status = AudioUnitGetPropertyInfo( status = AudioUnitGetPropertyInfo(
effectUnit, effectUnit,
kAudioUnitProperty_ParameterList, kAudioUnitProperty_ParameterList,
kAudioUnitScope_Global, kAudioUnitScope_Global,
0, 0,
&paramListSize, NULL); &propertySize,
NULL);
if (noErr != status) if (noErr != status)
{ {
if (NULL != error) if (NULL != error)
@ -351,7 +457,7 @@ static void UpdateChangeCountCallback(void *userData,
} }
return NO; return NO;
} }
UInt32 const paramCount = paramListSize / sizeof(AudioUnitParameterID); UInt32 const paramCount = propertySize / sizeof(AudioUnitParameterID);
if (0U < paramCount) if (0U < paramCount)
{ {
status = AUEventListenerCreate(UpdateChangeCountCallback, status = AUEventListenerCreate(UpdateChangeCountCallback,
@ -374,14 +480,14 @@ static void UpdateChangeCountCallback(void *userData,
} }
return NO; return NO;
} }
AudioUnitParameterID *const params = (AudioUnitParameterID *)malloc(paramListSize); AudioUnitParameterID *const params = (AudioUnitParameterID *)malloc(propertySize);
AudioUnitGetProperty( AudioUnitGetProperty(
effectUnit, effectUnit,
kAudioUnitProperty_ParameterList, kAudioUnitProperty_ParameterList,
kAudioUnitScope_Global, kAudioUnitScope_Global,
0, 0,
params, params,
&paramListSize); &propertySize);
if (noErr != status) if (noErr != status)
{ {
free(params); free(params);
@ -423,6 +529,35 @@ static void UpdateChangeCountCallback(void *userData,
} }
} }
propertySize = sizeof(presets);
status = AudioUnitGetProperty(effectUnit,
kAudioUnitProperty_FactoryPresets,
kAudioUnitScope_Global,
0,
&presets,
&propertySize);
if ((noErr != status) && (NULL != presets))
{
CFRelease(presets);
presets = NULL;
}
if (hasWrapper)
{
if ((nil != [desc objectForKey:ForceGenericViewKey])
&& [[desc objectForKey:ForceGenericViewKey] respondsToSelector:@selector(boolValue)])
{
forceGenericView = [[desc objectForKey:ForceGenericViewKey] boolValue];
[genericViewButton setState:(forceGenericView ? NSOnState : NSOffState)];
}
if ((nil != [desc objectForKey:WindowFrameKey])
&& [[desc objectForKey:WindowFrameKey] isKindOfClass:[NSString class]])
{
if (nil != restoreFrame) [restoreFrame release];
restoreFrame = [[NSString alloc] initWithString:[desc objectForKey:WindowFrameKey]];
}
}
[self loadEffectUI]; [self loadEffectUI];
return YES; return YES;
@ -456,10 +591,14 @@ static void UpdateChangeCountCallback(void *userData,
NSNumber const *typeVal = [NSNumber numberWithUnsignedLong:description.componentType]; NSNumber const *typeVal = [NSNumber numberWithUnsignedLong:description.componentType];
NSNumber const *subtypeVal = [NSNumber numberWithUnsignedLong:description.componentSubType]; NSNumber const *subtypeVal = [NSNumber numberWithUnsignedLong:description.componentSubType];
NSNumber const *manufacturerVal = [NSNumber numberWithUnsignedLong:description.componentManufacturer]; NSNumber const *manufacturerVal = [NSNumber numberWithUnsignedLong:description.componentManufacturer];
desc = [NSDictionary dictionaryWithObjectsAndKeys:typeVal, ComponentTypeKey, NSNumber const *forceGenericViewVal = [NSNumber numberWithBool:forceGenericView];
subtypeVal, ComponentSubTypeKey, NSString const *windowFrameVal = [window stringWithSavedFrame];
manufacturerVal, ComponentManufacturerKey, desc = [NSDictionary dictionaryWithObjectsAndKeys:typeVal, ComponentTypeKey,
classInfo, ClassInfoKey, subtypeVal, ComponentSubTypeKey,
manufacturerVal, ComponentManufacturerKey,
classInfo, ClassInfoKey,
forceGenericViewVal, ForceGenericViewKey,
windowFrameVal, WindowFrameKey,
nil]; nil];
} }
else if ([type isEqualToString:AUPresetDocumentType]) else if ([type isEqualToString:AUPresetDocumentType])
@ -498,13 +637,74 @@ static void UpdateChangeCountCallback(void *userData,
return data; return data;
} }
- (IBAction)toggleGenericView:(id)sender {
forceGenericView = (NSOnState == [sender state]);
if (nil != view)
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSViewFrameDidChangeNotification
object:nil];
[view removeFromSuperview];
view = nil;
}
if (0 != effectNode)
[self loadEffectUI];
}
- (IBAction)loadPreset:(id)sender {
OSStatus status;
CFIndex const idx = [sender tag];
CFIndex const total = (NULL == presets) ? 0 : CFArrayGetCount(presets);
if ((0 > idx) || (total <= idx))
{
NSAlert const *alert = [[NSAlert alloc] init];
[alert setMessageText:@"Invalid preset selected"];
[alert setInformativeText:[NSString stringWithFormat:@"Tried to select preset %ld of %ld",
(long)idx + 1,
(long)total]];
[alert beginSheetModalForWindow:window modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
return;
}
AUPreset const *preset = (AUPreset const *)CFArrayGetValueAtIndex(presets, idx);
status = AudioUnitSetProperty(effectUnit,
kAudioUnitProperty_PresentPreset,
kAudioUnitScope_Global,
0,
preset,
sizeof(AUPreset));
if (noErr != status)
{
NSAlert const *alert = [[NSAlert alloc] init];
[alert setMessageText:[NSString stringWithFormat:@"Error loading preset %@", preset->presetName]];
[alert setInformativeText:[NSString stringWithFormat:@"Error %ld encountered while setting AudioUnit property",
(long)status]];
[alert beginSheetModalForWindow:window modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
return;
}
AudioUnitParameter change = { effectUnit, kAUParameterListener_AnyParameter, 0, 0 };
status = AUParameterListenerNotify(NULL, NULL, &change);
if (noErr != status)
{
NSAlert const *alert = [[NSAlert alloc] init];
[alert setMessageText:[NSString stringWithFormat:@"Error notifying of parameter changes for preset %@",
preset->presetName]];
[alert setInformativeText:[NSString stringWithFormat:@"Error %ld encountered while sending notification",
(long)status]];
[alert beginSheetModalForWindow:window modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
return;
}
}
- (void)viewFrameDidChange:(NSNotification *)notification { - (void)viewFrameDidChange:(NSNotification *)notification {
NSRect const oldFrame = [window frame]; NSRect const oldFrame = [window frame];
NSRect const desired = [window frameRectForContentRect:[[notification object] frame]]; NSRect const desired = [window frameRectForContentRect:[[notification object] frame]];
NSRect const newFrame = NSMakeRect(oldFrame.origin.x, NSRect const newFrame = NSMakeRect(oldFrame.origin.x,
oldFrame.origin.y + oldFrame.size.height - desired.size.height, oldFrame.origin.y + oldFrame.size.height - headerSize.height- desired.size.height,
desired.size.width, desired.size.width,
desired.size.height); headerSize.height + desired.size.height);
[window setFrame:newFrame display:YES animate:NO]; [window setFrame:newFrame display:YES animate:NO];
} }
@ -582,11 +782,11 @@ static void UpdateChangeCountCallback(void *userData,
[menu addItem:[NSMenuItem separatorItem]]; [menu addItem:[NSMenuItem separatorItem]];
item = [menu addItemWithTitle:NSLocalizedString(@"Close", nil) action:@selector(performClose:) keyEquivalent:@"w"]; item = [menu addItemWithTitle:@"Close" action:@selector(performClose:) keyEquivalent:@"w"];
item = [menu addItemWithTitle:NSLocalizedString(@"Save", nil) action:@selector(saveDocument:) keyEquivalent:@"s"]; item = [menu addItemWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:@"s"];
item = [menu addItemWithTitle:NSLocalizedString(@"Save As…", nil) action:@selector(saveDocumentAs:) keyEquivalent:@"S"]; item = [menu addItemWithTitle:@"Save As…" action:@selector(saveDocumentAs:) keyEquivalent:@"S"];
item = [menu addItemWithTitle:NSLocalizedString(@"Save All", nil) action:@selector(saveAllDocuments:) keyEquivalent:@""]; item = [menu addItemWithTitle:@"Save All" action:@selector(saveAllDocuments:) keyEquivalent:@""];
item = [menu addItemWithTitle:NSLocalizedString(@"Revert to Saved", nil) action:@selector(revertDocumentToSaved:) keyEquivalent:@""]; item = [menu addItemWithTitle:@"Revert to Saved" action:@selector(revertDocumentToSaved:) keyEquivalent:@"u"];
} }
- (void)appendEditMenu:(NSMenu *)parent { - (void)appendEditMenu:(NSMenu *)parent {