DIP switches completed
This commit is contained in:
parent
a92ea6ea73
commit
96d5157ec3
|
@ -26,6 +26,7 @@
|
|||
|
||||
@property (readonly) NSString *supportPath;
|
||||
@property (readonly) NSString *nvramPath;
|
||||
@property (readonly) NSString *dipSwitchPath;
|
||||
|
||||
@property (readonly) NSArray *supportedFormats;
|
||||
|
||||
|
|
|
@ -59,9 +59,11 @@ static AppDelegate *sharedInstance = nil;
|
|||
|
||||
_supportPath = self.appSupportPath;
|
||||
_nvramPath = [_supportPath stringByAppendingPathComponent:@"NVRAM"];
|
||||
_dipSwitchPath = [_supportPath stringByAppendingPathComponent:@"DIPSwitches"];
|
||||
|
||||
NSArray *paths = @[
|
||||
_nvramPath
|
||||
_nvramPath,
|
||||
_dipSwitchPath,
|
||||
];
|
||||
|
||||
for (NSString *path in paths)
|
||||
|
@ -80,7 +82,13 @@ static AppDelegate *sharedInstance = nil;
|
|||
}
|
||||
|
||||
- (void) applicationWillTerminate:(NSNotification *) aNotification {
|
||||
NSLog(@"applicationWillTerminate");
|
||||
[_runloop cancel];
|
||||
|
||||
// Give the emulation thread some time to finish
|
||||
NSDate *start = [NSDate date];
|
||||
while (!_runloop.isFinished && start.timeIntervalSinceNow > -2)
|
||||
[NSThread sleepForTimeInterval:0.25];
|
||||
}
|
||||
|
||||
- (BOOL) application:(NSApplication *) sender
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
<key>NSSupportsAutomaticTermination</key>
|
||||
<true/>
|
||||
<key>NSSupportsSuddenTermination</key>
|
||||
<true/>
|
||||
<false/>
|
||||
<key>UTImportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
|
|
|
@ -33,12 +33,20 @@
|
|||
AudSoundPlay();
|
||||
}
|
||||
|
||||
- (NSString *) setName
|
||||
{
|
||||
return [NSString stringWithCString:BurnDrvGetText(DRV_NAME)
|
||||
encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
- (NSString *) title
|
||||
{
|
||||
return [NSString stringWithCString:BurnDrvGetText(DRV_FULLNAME)
|
||||
encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
#pragma mark - DIP switches
|
||||
|
||||
- (NSArray<FBDipSetting *> *) dipSwitches
|
||||
{
|
||||
if (!bDrvOkay)
|
||||
|
@ -50,11 +58,11 @@
|
|||
int offset = 0;
|
||||
BurnDIPInfo dipSwitch;
|
||||
for (int i = 0; BurnDrvGetDIPInfo(&dipSwitch, i) == 0; i++) {
|
||||
if (dipSwitch.nFlags == 0xf0)
|
||||
offset = dipSwitch.nInput;
|
||||
if (!dipSwitch.szText) // defaruto
|
||||
continue;
|
||||
|
||||
if (dipSwitch.nFlags == 0xf0)
|
||||
offset = dipSwitch.nInput;
|
||||
if (dipSwitch.nFlags & 0x40) {
|
||||
FBDipSetting *set = [FBDipSetting new];
|
||||
set.name = [NSString stringWithCString:dipSwitch.szText
|
||||
|
@ -71,14 +79,20 @@
|
|||
opt.start = dipSwitch.nInput + offset;
|
||||
opt.mask = dipSwitch.nMask;
|
||||
opt.setting = dipSwitch.nSetting;
|
||||
[(NSMutableArray *) active.switches addObject:opt];
|
||||
|
||||
// Default switch
|
||||
BurnDIPInfo dsw2;
|
||||
for (int j = 0; BurnDrvGetDIPInfo(&dsw2, j) == 0; j++)
|
||||
if (dsw2.nFlags == 0xff
|
||||
&& dsw2.nInput == dipSwitch.nInput
|
||||
if (dsw2.nFlags == 0xff && dsw2.nInput == dipSwitch.nInput
|
||||
&& (dsw2.nSetting & dipSwitch.nMask) == dipSwitch.nSetting)
|
||||
active.defaultIndex = active.selectedIndex = active.switches.count - 1;
|
||||
active.defaultIndex = active.selectedIndex = active.switches.count;
|
||||
|
||||
// Active switch
|
||||
struct GameInp *pgi = GameInp + opt.start;
|
||||
if ((pgi->Input.Constant.nConst & opt.mask) == dipSwitch.nSetting)
|
||||
active.selectedIndex = active.switches.count;
|
||||
|
||||
[(NSMutableArray *) active.switches addObject:opt];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,9 +104,63 @@
|
|||
if (bDrvOkay) {
|
||||
struct GameInp *pgi = GameInp + option.start;
|
||||
pgi->Input.Constant.nConst = (pgi->Input.Constant.nConst & ~option.mask) | (option.setting & option.mask);
|
||||
self.dipSwitchesDirty = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) saveDipState:(NSString *) path
|
||||
{
|
||||
NSLog(@"saveDipState");
|
||||
|
||||
NSArray<FBDipSetting *> *switches = self.dipSwitches;
|
||||
if (!switches || switches.count < 1)
|
||||
return YES;
|
||||
|
||||
for (FBDipSetting *sw in switches)
|
||||
if (sw.defaultIndex != sw.selectedIndex)
|
||||
goto save;
|
||||
|
||||
return YES;
|
||||
|
||||
save:
|
||||
FILE *f = fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "w");
|
||||
if (!f)
|
||||
return NO;
|
||||
|
||||
for (FBDipSetting *sw in switches) {
|
||||
FBDipOption *opt = sw.switches[sw.selectedIndex];
|
||||
fprintf(f, "%x %d %02x\n", opt.start, sw.selectedIndex, opt.setting);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) restoreDipState:(NSString *) path
|
||||
{
|
||||
NSLog(@"restoreDipState");
|
||||
|
||||
NSArray<FBDipSetting *> *switches = self.dipSwitches;
|
||||
if (!switches || switches.count < 1)
|
||||
return YES;
|
||||
|
||||
FILE *f = fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "r");
|
||||
if (!f)
|
||||
return NO;
|
||||
|
||||
int swIndex;
|
||||
uint32 start;
|
||||
uint32 setting;
|
||||
for (int i = 0; fscanf(f, "%x %d %x", &start, &swIndex, &setting) == 3 && i < switches.count; i++) {
|
||||
FBDipSetting *sw = switches[i];
|
||||
if (sw.selectedIndex != swIndex && swIndex < sw.switches.count)
|
||||
[self applyDip:sw.switches[swIndex]];
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - FBDipSetting
|
||||
|
|
|
@ -43,7 +43,8 @@
|
|||
|
||||
@interface FBMainThread : NSThread
|
||||
|
||||
@property (readonly) NSString *running;
|
||||
@property (readonly) NSString *runningPath;
|
||||
@property BOOL dipSwitchesDirty;
|
||||
|
||||
- (NSString *) log;
|
||||
- (void) load:(NSString *) path;
|
||||
|
@ -59,8 +60,11 @@
|
|||
- (void) setPaused:(BOOL) isPaused;
|
||||
|
||||
- (NSString *) title;
|
||||
- (NSString *) setName;
|
||||
|
||||
- (NSArray<FBDipSetting *> *) dipSwitches;
|
||||
- (void) applyDip:(FBDipOption *) option;
|
||||
- (BOOL) restoreDipState:(NSString *) path;
|
||||
- (BOOL) saveDipState:(NSString *) path;
|
||||
|
||||
@end
|
||||
|
|
|
@ -83,7 +83,7 @@ typedef enum LogEntryType {
|
|||
|
||||
while (!self.isCancelled) {
|
||||
if (pathToLoad == nil) {
|
||||
[NSThread sleepForTimeInterval:.5]; // Pause until there's something to load
|
||||
[NSThread sleepForTimeInterval:.1]; // Pause until there's something to load
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,13 @@ typedef enum LogEntryType {
|
|||
continue;
|
||||
}
|
||||
|
||||
_running = pathToLoad;
|
||||
// Load DIP switch config
|
||||
NSString *dipPath = [AppDelegate.sharedInstance.dipSwitchPath stringByAppendingPathComponent:
|
||||
[NSString stringWithFormat:@"%@.dip", self.setName]];
|
||||
[self restoreDipState:dipPath];
|
||||
_dipSwitchesDirty = NO;
|
||||
|
||||
_runningPath = pathToLoad;
|
||||
pathToLoad = nil;
|
||||
|
||||
@synchronized (observers) {
|
||||
|
@ -134,9 +140,14 @@ typedef enum LogEntryType {
|
|||
}
|
||||
}
|
||||
|
||||
// Runtime loop
|
||||
while (!self.isCancelled && pathToLoad == nil)
|
||||
MainFrame();
|
||||
|
||||
// Save DIP switch config
|
||||
if (_dipSwitchesDirty)
|
||||
[self saveDipState:dipPath];
|
||||
|
||||
@synchronized (observers) {
|
||||
for (id<FBMainThreadDelegate> o in observers) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
@ -146,10 +157,12 @@ typedef enum LogEntryType {
|
|||
}
|
||||
}
|
||||
|
||||
_running = nil;
|
||||
_runningPath = nil;
|
||||
|
||||
MainEnd();
|
||||
}
|
||||
|
||||
NSLog(@"Exiting FBMainThread");
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue