From 9b3223478cd42b15522f8275051ca40a44df8c11 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Thu, 2 Nov 2023 22:16:03 -0400 Subject: [PATCH] Eliminate the hard-coded slot values and use the slot name + dictionary for saving between machines. --- Ample/Slot.h | 11 +--- Ample/Slot.m | 110 ++++++++--------------------------- Ample/SlotViewController.m | 115 ++++++++++++++++--------------------- 3 files changed, 72 insertions(+), 164 deletions(-) diff --git a/Ample/Slot.h b/Ample/Slot.h index 485de99..dee2c1f 100644 --- a/Ample/Slot.h +++ b/Ample/Slot.h @@ -10,16 +10,6 @@ #import #import "Media.h" -/* number of slot types. bitmask used so should be < sizeof(unsigned *8) */ -#define SLOT_COUNT 28 -static_assert(SLOT_COUNT <= sizeof(unsigned) * 8, "too many slot types"); - -#define kSMARTPORT_SLOT 1 -#define kBIOS_SLOT 2 - -#ifndef SIZEOF -#define SIZEOF(x) (sizeof(x) / sizeof(x[0])) -#endif //NS_ASSUME_NONNULL_BEGIN @class Slot, SlotOption, SlotTableCellView; @@ -36,6 +26,7 @@ static_assert(SLOT_COUNT <= sizeof(unsigned) * 8, "too many slot types"); @property (readonly) NSArray *menuItems; @property (readonly) SlotOption *selectedItem; +@property (readonly) NSString *selectedValue; -(NSArray *)args; -(NSDictionary *)serialize; diff --git a/Ample/Slot.m b/Ample/Slot.m index 43b9c1e..4b7bb22 100644 --- a/Ample/Slot.m +++ b/Ample/Slot.m @@ -72,48 +72,6 @@ static NSArray *DeepCopyArray(NSArray *src) { @implementation Slot -static NSDictionary *IndexMap = nil; -+(void)load { - - IndexMap = @{ - @"ramsize": @0, - - @"smartport": @1, - @"bios": @2, - - @"sl0": @3, - @"sl1": @4, - @"sl2": @5, - @"sl3": @6, - @"sl4": @7, - @"sl5": @8, - @"sl6": @9, - @"sl7": @10, - @"exp": @11, - @"aux": @12, - @"rs232": @13, - @"gameio": @14, - @"modem": @15, - @"printer": @16, - - //nubus mac - @"nb9": @17, - @"nba": @18, - @"nbb": @19, - @"nbc": @20, - @"nbd": @21, - @"nbe": @22, - - @"pds": @23, - @"pds030": @24, - - @"centronics": @25, - @"mdin": @26, - @"mdout": @27 - }; - static_assert(kSMARTPORT_SLOT == 1, "Smartport != 1"); - static_assert(kBIOS_SLOT == 2, "Bios != 2"); -} -(void)reset { [self setSelectedIndex: _defaultIndex >= 0 ? _defaultIndex : 0]; @@ -171,7 +129,7 @@ static NSDictionary *IndexMap = nil; // { 'sl3' : 'uthernet' } // special case for smartport since the name isn't used. - if (_index == kSMARTPORT_SLOT) { + if ([_name isEqualToString: @"-smartport"]) { SlotOption *option = [_options objectAtIndex: _selectedIndex]; [option reserialize: dict]; return; @@ -230,9 +188,14 @@ static NSDictionary *IndexMap = nil; [option buildMedia: &media]; return media; - } +-(NSString *)selectedValue { + + if (_selectedIndex < 0) return nil; + if (_selectedIndex >= [_options count]) return nil; + return [[_options objectAtIndex: _selectedIndex] value]; +} -(NSArray *)selectedChildren { if (_selectedIndex < 0) return nil; @@ -288,21 +251,22 @@ static NSDictionary *IndexMap = nil; if (c != '-') _name = p; } - -(instancetype)initWithDictionary: (NSDictionary *)data devices: (NSDictionary *)devices { + return [self initWithDictionary: data devices: devices index: 0]; +} + +-(instancetype)initWithDictionary: (NSDictionary *)data devices: (NSDictionary *)devices index: (NSInteger)index { BOOL topLevel = NO; _selectedIndex = -1; _defaultIndex = -1; - _index = -1; + _index = index; _name = [data objectForKey: @"name"]; _title = [data objectForKey: @"description"]; - - NSNumber *x = [IndexMap objectForKey: _name]; - if (x) { + + if (index < 0x10000) { topLevel = YES; - _index = [x integerValue]; _name = [@"-" stringByAppendingString: _name]; _title = [_title stringByAppendingString: @":"]; } @@ -310,14 +274,13 @@ static NSDictionary *IndexMap = nil; NSArray *op = [data objectForKey: @"options"]; NSMutableArray *options = [NSMutableArray arrayWithCapacity: [op count]]; - - NSInteger index = 0; + NSInteger ix = 0; for (NSDictionary *d in op) { SlotOption *o = [[SlotOption alloc] initWithDictionary: d devices: devices]; if ([o isDefault]) { - _defaultIndex = index; + _defaultIndex = ix; } - ++index; + ++ix; if (topLevel) { [o setKeyPath: _name]; NSArray *tmp = [o children]; @@ -338,36 +301,6 @@ static NSDictionary *IndexMap = nil; return self; } -#if 0 --(instancetype)initWithName: (NSString *)name title: (NSString *)title data: (NSArray *)data { - - _name = [name copy]; - _title = [title copy]; - _selectedIndex = -1; - _defaultIndex = -1; - _index = -1; - - NSMutableArray *options = [NSMutableArray arrayWithCapacity: [data count]]; - //NSMutableArray *menuItems = [NSMutableArray arrayWithCapacity: [data count]]; - - NSInteger index = 0; - for (NSDictionary *d in data) { - SlotOption *o = [[SlotOption alloc] initWithDictionary: d]; - if ([o isDefault]) { - _defaultIndex = index; - } - ++index; - [options addObject: o]; - } - _options = options; - //_menuItems = menuItems; - - _selectedIndex = _defaultIndex; - if (_selectedIndex < 0) _selectedIndex = 0; - - return self; -} -#endif -(NSArray *)menuItems { //if (_menuItems) return _menuItems; @@ -406,7 +339,8 @@ static NSDictionary *IndexMap = nil; // [menu setItemArray: ] doesn't work prior to 10.14, apparently. [menu removeAllItems]; - if (_index == kSMARTPORT_SLOT) { + + if ([_name isEqualToString: @"-smartport"]) { //[menu setItemArray: @[]]; [button setHidden: YES]; } else { @@ -630,7 +564,7 @@ NSDictionary *BuildDevices(NSArray *array) { NSArray *data = MapArray(slots, ^(id o){ - Slot *s = [[Slot alloc] initWithDictionary: o devices: nil]; + Slot *s = [[Slot alloc] initWithDictionary: o devices: nil index: 0]; return s; }); @@ -658,9 +592,11 @@ NSArray *BuildSlots(NSString *name, NSDictionary *data) { NSMutableArray *rv = [NSMutableArray arrayWithCapacity: [slots count]]; NSDictionary *devices = BuildDevices([data objectForKey: @"devices"]); + + unsigned ix = 0; for (NSDictionary *d in slots) { - Slot *s = [[Slot alloc] initWithDictionary: d devices: devices]; + Slot *s = [[Slot alloc] initWithDictionary: d devices: devices index: ++ix]; [rv addObject: s]; } diff --git a/Ample/SlotViewController.m b/Ample/SlotViewController.m index 1573069..9027ea5 100644 --- a/Ample/SlotViewController.m +++ b/Ample/SlotViewController.m @@ -16,7 +16,7 @@ #import - +#define MAX_SLOTS 32 static unsigned RootKey = 0; @@ -31,18 +31,13 @@ static unsigned RootKey = 0; @implementation SlotViewController { NSArray *_root; - unsigned _slots_explicit; - unsigned _slots_valid; - unsigned _slots_default; - - Slot *_slot_object[SLOT_COUNT]; - NSString *_slot_value[SLOT_COUNT]; // when explicitely set. - - Media _slot_media[SLOT_COUNT]; + Media _slot_media[MAX_SLOTS]; Media _machine_media; NSDictionary *_machine_data; - + + NSMutableDictionary *_slotValues; + IBOutlet NSPopover *_popover; BOOL _loadingBookmark; @@ -55,6 +50,7 @@ static unsigned RootKey = 0; _root = @[]; objc_setAssociatedObject(_outlineView, &RootKey, _root, OBJC_ASSOCIATION_RETAIN); + _slotValues = [NSMutableDictionary new]; //[_outlineView setIndentationPerLevel: 2.0]; } @@ -66,16 +62,13 @@ static unsigned RootKey = 0; [_outlineView reloadData]; - _slots_valid = 0; - _slots_explicit = 0; - _slots_default = 0; + [_slotValues removeAllObjects]; + _machine_media = EmptyMedia; _machine_data = nil; - for (unsigned i = 0; i < SLOT_COUNT; ++i) { + for (unsigned i = 0; i < MAX_SLOTS; ++i) { _slot_media[i] = EmptyMedia; - _slot_object[i] = nil; - _slot_value[i] = nil; } [self setResolution: NSMakeSize(0, 0)]; @@ -86,10 +79,8 @@ static unsigned RootKey = 0; -(void)loadMachine { - NSDictionary *d = MameMachine(_machine); - if (!d) { [self resetMachine]; return; @@ -103,39 +94,33 @@ static unsigned RootKey = 0; } [self setResolution: res]; - _slots_valid = 0; - //_slots_explicit = 0; - _slots_default = 0; _machine_media = MediaFromDictionary([d objectForKey: @"media"]); _machine_data = d; - for (unsigned i = 0; i < SLOT_COUNT; ++i) { + for (unsigned i = 0; i < MAX_SLOTS; ++i) { _slot_media[i] = EmptyMedia; - _slot_object[i] = nil; } - - _slot_value[kBIOS_SLOT] = nil; // don't copy over to other machines. extern NSArray *BuildSlots(NSString *name, NSDictionary *data); _root = BuildSlots(_machine, d); objc_setAssociatedObject(_outlineView, &RootKey, _root, OBJC_ASSOCIATION_RETAIN); for (Slot *item in _root) { - NSInteger index = [item index]; - if (index < 0) continue; - unsigned mask = 1 << index; + NSString *name = [item name]; + NSInteger index = [item index] - 1; + if (index < 0 || index >= MAX_SLOTS) continue; - _slots_valid |= mask; - if ([item defaultIndex] >= 0) - _slots_default |= mask; - - if (_slot_value[index]) - [item selectValue: _slot_value[index]]; + if ([name isEqualToString: @"-bios"]) continue; + NSString *v = [_slotValues objectForKey: name]; + if (v) { + [item selectValue: v]; + } + // TODO -- reset to default index??? + _slot_media[index] = [item selectedMedia]; - _slot_object[index] = item; } @@ -165,12 +150,9 @@ static unsigned RootKey = 0; Media media = EmptyMedia; - unsigned mask = 1; - for (unsigned i = 0; i < SLOT_COUNT; ++i, mask <<= 1) { + for (unsigned i = 0; i < MAX_SLOTS; ++i) { - if (_slots_valid & mask) { - MediaAdd(&media, &_slot_media[i]); - } + MediaAdd(&media, &_slot_media[i]); } // machine media last. MediaAdd(&media, &_machine_media); @@ -196,34 +178,29 @@ static unsigned RootKey = 0; BOOL direct = YES; NSInteger index = [sender tag]; - if (index < 0) return; // - if (index >= 0 && index < SLOT_COUNT) { + if (index < 0x10000) { direct = YES; } else { direct = NO; index &= ~0x10000; } - if (index >= SLOT_COUNT) return; // - unsigned mask = 1 << index; - - - // index 0 = ram = special case... + index--; + if (index < 0 || index >= MAX_SLOTS) return; // SlotOption *o = [[sender selectedItem] representedObject]; - Slot *item = _slot_object[index]; + Slot *item = [_root objectAtIndex: index]; if (direct) { - _slots_explicit |= mask; - _slot_value[index] = [o value]; - //_slots_default &= ~mask; + NSString *name = [item name]; + NSString *value = [o value]; + [_slotValues setObject: value forKey: name]; } Media media = [item selectedMedia]; if (!MediaEqual(&media, &_slot_media[index])) { _slot_media[index] = media; [self rebuildMedia]; - } // needs to reload children if expanded. @@ -244,9 +221,9 @@ static unsigned RootKey = 0; #endif NSInteger index = [sender tag]; - if (index < 0 || index >= SLOT_COUNT) return; - - Slot *item = _slot_object[index]; + if (index <= 0 || index >= 0x10000) return; + index--; + Slot *item = [_root objectAtIndex: index]; NSArray *children = [item selectedChildren]; objc_setAssociatedObject(_childOutlineView, &RootKey, children, OBJC_ASSOCIATION_RETAIN); @@ -266,15 +243,19 @@ static unsigned RootKey = 0; -(IBAction)resetSlots:(id)sender { - _slots_explicit = 0; - for (unsigned i = 0; i < SLOT_COUNT; ++i) { + + //_slots_explicit = 0; + for (unsigned i = 0; i < MAX_SLOTS; ++i) { _slot_media[i] = EmptyMedia; - _slot_value[i] = nil; } for (Slot *item in _root) { + NSString *name = [item name]; + + [_slotValues removeObjectForKey: name]; + [item reset]; // if children, reset them too... - NSInteger index = [item index]; + NSInteger index = [item index] - 1; if (index < 0) continue; _slot_media[index] = [item selectedMedia]; } @@ -367,19 +348,19 @@ static unsigned RootKey = 0; for (Slot *item in _root) { [item reserialize: dict]; - NSInteger index = [item index]; - if (index >= 0 && index < SLOT_COUNT) { - unsigned mask = 1 << index; - + NSInteger index = [item index] - 1; + if (index >= 0 && index < MAX_SLOTS) { + + NSString *name = [item name]; + [_slotValues removeObjectForKey: name]; + if ([item defaultIndex] != [item selectedIndex]) { - _slots_explicit |= mask; // grrr. - _slot_value[index] = [[item selectedItem] value]; + NSString *v = [item selectedValue]; + if (v) [_slotValues setObject: v forKey: name]; } _slot_media[index] = [item selectedMedia]; } - - ++index; } // need to do it here so it propogate to media view.