1// Copyright (c) Akop Karapetyan 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#import "FBMainThread.h" 16 17#import "AppDelegate.h" 18 19#include "burner.h" 20#include "burnint.h" 21#include "driverlist.h" 22 23// Placing burner.h stuff in the NSThread file 24// messes with thread execution for some reason, 25// so I'm implementing it as a category - AK 26 27@implementation FBMainThread (Etc) 28 29- (BOOL) isPaused 30{ 31 return bRunPause; 32} 33 34- (void) setPaused:(BOOL) isPaused 35{ 36 if (!bDrvOkay || bRunPause == isPaused) 37 return; 38 39 bRunPause = isPaused; 40 if (isPaused) 41 AudSoundStop(); 42 else 43 AudSoundPlay(); 44} 45 46- (NSString *) setName 47{ 48 return [NSString stringWithCString:BurnDrvGetText(DRV_NAME) 49 encoding:NSASCIIStringEncoding]; 50} 51 52- (NSString *) title 53{ 54 if (!bDrvOkay) 55 return nil; 56 57 const wchar_t *unicodeName = pDriver[nBurnDrvActive]->szFullNameW; 58 if (unicodeName) 59 return [[NSString alloc] initWithBytes:unicodeName 60 length:sizeof(wchar_t) * wcslen(unicodeName) 61 encoding:NSUTF32LittleEndianStringEncoding]; 62 63 const char *asciiName = pDriver[nBurnDrvActive]->szFullNameA; 64 if (asciiName) 65 return [NSString stringWithCString:asciiName 66 encoding:NSASCIIStringEncoding]; 67 68 return nil; 69} 70 71#pragma mark - DIP switches 72 73- (NSArray<FBDipSetting *> *) dipSwitches 74{ 75 if (!bDrvOkay) 76 return nil; 77 78 NSMutableArray *switches = [NSMutableArray new]; 79 FBDipSetting *active; 80 81 int offset = 0; 82 BurnDIPInfo dipSwitch; 83 for (int i = 0; BurnDrvGetDIPInfo(&dipSwitch, i) == 0; i++) { 84 if (!dipSwitch.szText) // defaruto 85 continue; 86 87 if (dipSwitch.nFlags == 0xf0) 88 offset = dipSwitch.nInput; 89 if (dipSwitch.nFlags & 0x40) { 90 FBDipSetting *set = [FBDipSetting new]; 91 set.name = [NSString stringWithCString:dipSwitch.szText 92 encoding:NSUTF8StringEncoding]; 93 94 active = set; 95 set.selectedIndex = 0; 96 set.switches = [NSMutableArray new]; 97 [switches addObject:set]; 98 } else { 99 FBDipOption *opt = [FBDipOption new]; 100 opt.name = [NSString stringWithCString:dipSwitch.szText 101 encoding:NSUTF8StringEncoding]; 102 opt.start = dipSwitch.nInput + offset; 103 opt.mask = dipSwitch.nMask; 104 opt.setting = dipSwitch.nSetting; 105 106 // Default switch 107 BurnDIPInfo dsw2; 108 for (int j = 0; BurnDrvGetDIPInfo(&dsw2, j) == 0; j++) 109 if (dsw2.nFlags == 0xff && dsw2.nInput == dipSwitch.nInput 110 && (dsw2.nSetting & dipSwitch.nMask) == dipSwitch.nSetting) 111 active.defaultIndex = active.selectedIndex = active.switches.count; 112 113 // Active switch 114 struct GameInp *pgi = GameInp + opt.start; 115 if ((pgi->Input.Constant.nConst & opt.mask) == dipSwitch.nSetting) 116 active.selectedIndex = active.switches.count; 117 118 [(NSMutableArray *) active.switches addObject:opt]; 119 } 120 } 121 122 return switches; 123} 124 125- (void) applyDip:(FBDipOption *) option 126{ 127 if (bDrvOkay) { 128 struct GameInp *pgi = GameInp + option.start; 129 pgi->Input.Constant.nConst = (pgi->Input.Constant.nConst & ~option.mask) | (option.setting & option.mask); 130 self.dipSwitchesDirty = YES; 131 } 132} 133 134- (BOOL) saveDipState:(NSString *) path 135{ 136 NSLog(@"saveDipState"); 137 138 NSArray<FBDipSetting *> *switches = self.dipSwitches; 139 if (!switches || switches.count < 1) 140 return YES; 141 142 for (FBDipSetting *sw in switches) 143 if (sw.defaultIndex != sw.selectedIndex) 144 goto save; 145 146 return YES; 147 148save: 149 FILE *f = fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "w"); 150 if (!f) 151 return NO; 152 153 for (FBDipSetting *sw in switches) { 154 FBDipOption *opt = sw.switches[sw.selectedIndex]; 155 fprintf(f, "%x %d %02x\n", opt.start, sw.selectedIndex, opt.setting); 156 } 157 158 fclose(f); 159 return YES; 160} 161 162- (BOOL) restoreDipState:(NSString *) path 163{ 164 NSLog(@"restoreDipState"); 165 166 NSArray<FBDipSetting *> *switches = self.dipSwitches; 167 if (!switches || switches.count < 1) 168 return YES; 169 170 FILE *f = fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "r"); 171 if (!f) 172 return NO; 173 174 int swIndex; 175 uint32 start; 176 uint32 setting; 177 for (int i = 0; fscanf(f, "%x %d %x", &start, &swIndex, &setting) == 3 && i < switches.count; i++) { 178 FBDipSetting *sw = switches[i]; 179 if (sw.selectedIndex != swIndex && swIndex < sw.switches.count) 180 [self applyDip:sw.switches[swIndex]]; 181 } 182 183 fclose(f); 184 185 [AppDelegate.sharedInstance.input simReset]; 186 return YES; 187} 188 189@end 190 191#pragma mark - FBDipSetting 192 193@implementation FBDipSetting 194 195- (instancetype) init 196{ 197 if (self = [super init]) { 198 _switches = [NSMutableArray new]; 199 } 200 return self; 201} 202 203@end 204 205#pragma mark - FBDipOption 206 207@implementation FBDipOption 208 209@end 210