Eliminate the hard-coded slot values and use the slot name + dictionary for saving between machines.

This commit is contained in:
Kelvin Sherlock 2023-11-02 22:16:03 -04:00
parent 2198467def
commit 9b3223478c
3 changed files with 72 additions and 164 deletions

View File

@ -10,16 +10,6 @@
#import <Cocoa/Cocoa.h>
#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;

View File

@ -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];
}

View File

@ -16,7 +16,7 @@
#import <objc/runtime.h>
#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.