├── .gitignore ├── DOSComLoader ├── DOSComLoader.xcodeproj │ └── project.pbxproj └── DOSComLoader │ ├── ComLoader.h │ ├── ComLoader.m │ └── Info.plist ├── DOSExeLoader ├── DOSExeLoader.xcodeproj │ └── project.pbxproj └── DOSExeLoader │ ├── Info.plist │ ├── MZLoader.h │ ├── MZLoader.mm │ └── mz.h ├── HopperDos.xcworkspace └── contents.xcworkspacedata ├── Intel16CPU ├── Intel16CPU.xcodeproj │ └── project.pbxproj └── Intel16CPU │ ├── Info.plist │ ├── Intel16CPU.h │ ├── Intel16CPU.mm │ ├── Intel16Ctx.h │ ├── Intel16Ctx.m │ ├── OpComment.h │ ├── OpComment.mm │ ├── ints.json │ └── ports.json ├── LICENSE ├── README.md ├── scripts ├── DosExportSym.py └── DosImportSym.py └── tools └── mk_ints.py /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | DerivedData 3 | build 4 | xcuserdata 5 | 6 | -------------------------------------------------------------------------------- /DOSComLoader/DOSComLoader.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 52EDA4741E9073A70088D4FA /* ComLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 52EDA4731E9073A70088D4FA /* ComLoader.m */; }; 11 | 52EDA4771E9073E70088D4FA /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52EDA4761E9073E70088D4FA /* CoreFoundation.framework */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXFileReference section */ 15 | 52EDA4691E90737E0088D4FA /* DOSComLoader.hopperLoader */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DOSComLoader.hopperLoader; sourceTree = BUILT_PRODUCTS_DIR; }; 16 | 52EDA46C1E90737E0088D4FA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 17 | 52EDA4721E9073A70088D4FA /* ComLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComLoader.h; sourceTree = ""; }; 18 | 52EDA4731E9073A70088D4FA /* ComLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ComLoader.m; sourceTree = ""; }; 19 | 52EDA4761E9073E70088D4FA /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; 20 | /* End PBXFileReference section */ 21 | 22 | /* Begin PBXFrameworksBuildPhase section */ 23 | 52EDA4661E90737E0088D4FA /* Frameworks */ = { 24 | isa = PBXFrameworksBuildPhase; 25 | buildActionMask = 2147483647; 26 | files = ( 27 | 52EDA4771E9073E70088D4FA /* CoreFoundation.framework in Frameworks */, 28 | ); 29 | runOnlyForDeploymentPostprocessing = 0; 30 | }; 31 | /* End PBXFrameworksBuildPhase section */ 32 | 33 | /* Begin PBXGroup section */ 34 | 52EDA4601E90737E0088D4FA = { 35 | isa = PBXGroup; 36 | children = ( 37 | 52EDA46B1E90737E0088D4FA /* DOSComLoader */, 38 | 52EDA46A1E90737E0088D4FA /* Products */, 39 | 52EDA4751E9073E70088D4FA /* Frameworks */, 40 | ); 41 | sourceTree = ""; 42 | }; 43 | 52EDA46A1E90737E0088D4FA /* Products */ = { 44 | isa = PBXGroup; 45 | children = ( 46 | 52EDA4691E90737E0088D4FA /* DOSComLoader.hopperLoader */, 47 | ); 48 | name = Products; 49 | sourceTree = ""; 50 | }; 51 | 52EDA46B1E90737E0088D4FA /* DOSComLoader */ = { 52 | isa = PBXGroup; 53 | children = ( 54 | 52EDA4721E9073A70088D4FA /* ComLoader.h */, 55 | 52EDA4731E9073A70088D4FA /* ComLoader.m */, 56 | 52EDA46C1E90737E0088D4FA /* Info.plist */, 57 | ); 58 | path = DOSComLoader; 59 | sourceTree = ""; 60 | }; 61 | 52EDA4751E9073E70088D4FA /* Frameworks */ = { 62 | isa = PBXGroup; 63 | children = ( 64 | 52EDA4761E9073E70088D4FA /* CoreFoundation.framework */, 65 | ); 66 | name = Frameworks; 67 | sourceTree = ""; 68 | }; 69 | /* End PBXGroup section */ 70 | 71 | /* Begin PBXNativeTarget section */ 72 | 52EDA4681E90737E0088D4FA /* DOSComLoader */ = { 73 | isa = PBXNativeTarget; 74 | buildConfigurationList = 52EDA46F1E90737E0088D4FA /* Build configuration list for PBXNativeTarget "DOSComLoader" */; 75 | buildPhases = ( 76 | 52EDA4651E90737E0088D4FA /* Sources */, 77 | 52EDA4661E90737E0088D4FA /* Frameworks */, 78 | 52EDA4671E90737E0088D4FA /* Resources */, 79 | ); 80 | buildRules = ( 81 | ); 82 | dependencies = ( 83 | ); 84 | name = DOSComLoader; 85 | productName = DOSComLoader; 86 | productReference = 52EDA4691E90737E0088D4FA /* DOSComLoader.hopperLoader */; 87 | productType = "com.apple.product-type.bundle"; 88 | }; 89 | /* End PBXNativeTarget section */ 90 | 91 | /* Begin PBXProject section */ 92 | 52EDA4611E90737E0088D4FA /* Project object */ = { 93 | isa = PBXProject; 94 | attributes = { 95 | LastUpgradeCheck = 1030; 96 | ORGANIZATIONNAME = bjfn; 97 | TargetAttributes = { 98 | 52EDA4681E90737E0088D4FA = { 99 | CreatedOnToolsVersion = 8.3; 100 | ProvisioningStyle = Automatic; 101 | }; 102 | }; 103 | }; 104 | buildConfigurationList = 52EDA4641E90737E0088D4FA /* Build configuration list for PBXProject "DOSComLoader" */; 105 | compatibilityVersion = "Xcode 3.2"; 106 | developmentRegion = English; 107 | hasScannedForEncodings = 0; 108 | knownRegions = ( 109 | English, 110 | en, 111 | ); 112 | mainGroup = 52EDA4601E90737E0088D4FA; 113 | productRefGroup = 52EDA46A1E90737E0088D4FA /* Products */; 114 | projectDirPath = ""; 115 | projectRoot = ""; 116 | targets = ( 117 | 52EDA4681E90737E0088D4FA /* DOSComLoader */, 118 | ); 119 | }; 120 | /* End PBXProject section */ 121 | 122 | /* Begin PBXResourcesBuildPhase section */ 123 | 52EDA4671E90737E0088D4FA /* Resources */ = { 124 | isa = PBXResourcesBuildPhase; 125 | buildActionMask = 2147483647; 126 | files = ( 127 | ); 128 | runOnlyForDeploymentPostprocessing = 0; 129 | }; 130 | /* End PBXResourcesBuildPhase section */ 131 | 132 | /* Begin PBXSourcesBuildPhase section */ 133 | 52EDA4651E90737E0088D4FA /* Sources */ = { 134 | isa = PBXSourcesBuildPhase; 135 | buildActionMask = 2147483647; 136 | files = ( 137 | 52EDA4741E9073A70088D4FA /* ComLoader.m in Sources */, 138 | ); 139 | runOnlyForDeploymentPostprocessing = 0; 140 | }; 141 | /* End PBXSourcesBuildPhase section */ 142 | 143 | /* Begin XCBuildConfiguration section */ 144 | 52EDA46D1E90737E0088D4FA /* Debug */ = { 145 | isa = XCBuildConfiguration; 146 | buildSettings = { 147 | ALWAYS_SEARCH_USER_PATHS = NO; 148 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 149 | CLANG_ANALYZER_NONNULL = YES; 150 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 151 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 152 | CLANG_CXX_LIBRARY = "libc++"; 153 | CLANG_ENABLE_MODULES = YES; 154 | CLANG_ENABLE_OBJC_ARC = YES; 155 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 156 | CLANG_WARN_BOOL_CONVERSION = YES; 157 | CLANG_WARN_COMMA = YES; 158 | CLANG_WARN_CONSTANT_CONVERSION = YES; 159 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 160 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 161 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 162 | CLANG_WARN_EMPTY_BODY = YES; 163 | CLANG_WARN_ENUM_CONVERSION = YES; 164 | CLANG_WARN_INFINITE_RECURSION = YES; 165 | CLANG_WARN_INT_CONVERSION = YES; 166 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 167 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 168 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 169 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 170 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 171 | CLANG_WARN_STRICT_PROTOTYPES = YES; 172 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 173 | CLANG_WARN_UNREACHABLE_CODE = YES; 174 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 175 | CODE_SIGN_IDENTITY = "-"; 176 | COPY_PHASE_STRIP = NO; 177 | DEBUG_INFORMATION_FORMAT = dwarf; 178 | ENABLE_STRICT_OBJC_MSGSEND = YES; 179 | ENABLE_TESTABILITY = YES; 180 | GCC_C_LANGUAGE_STANDARD = gnu99; 181 | GCC_DYNAMIC_NO_PIC = NO; 182 | GCC_NO_COMMON_BLOCKS = YES; 183 | GCC_OPTIMIZATION_LEVEL = 0; 184 | GCC_PREPROCESSOR_DEFINITIONS = ( 185 | "DEBUG=1", 186 | "$(inherited)", 187 | ); 188 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 189 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 190 | GCC_WARN_UNDECLARED_SELECTOR = YES; 191 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 192 | GCC_WARN_UNUSED_FUNCTION = YES; 193 | GCC_WARN_UNUSED_VARIABLE = YES; 194 | HEADER_SEARCH_PATHS = "$(SRCROOT)/../../include"; 195 | MACOSX_DEPLOYMENT_TARGET = 10.12; 196 | MTL_ENABLE_DEBUG_INFO = YES; 197 | ONLY_ACTIVE_ARCH = YES; 198 | SDKROOT = macosx; 199 | }; 200 | name = Debug; 201 | }; 202 | 52EDA46E1E90737E0088D4FA /* Release */ = { 203 | isa = XCBuildConfiguration; 204 | buildSettings = { 205 | ALWAYS_SEARCH_USER_PATHS = NO; 206 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 207 | CLANG_ANALYZER_NONNULL = YES; 208 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 209 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 210 | CLANG_CXX_LIBRARY = "libc++"; 211 | CLANG_ENABLE_MODULES = YES; 212 | CLANG_ENABLE_OBJC_ARC = YES; 213 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 214 | CLANG_WARN_BOOL_CONVERSION = YES; 215 | CLANG_WARN_COMMA = YES; 216 | CLANG_WARN_CONSTANT_CONVERSION = YES; 217 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 218 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 219 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 220 | CLANG_WARN_EMPTY_BODY = YES; 221 | CLANG_WARN_ENUM_CONVERSION = YES; 222 | CLANG_WARN_INFINITE_RECURSION = YES; 223 | CLANG_WARN_INT_CONVERSION = YES; 224 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 225 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 226 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 227 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 228 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 229 | CLANG_WARN_STRICT_PROTOTYPES = YES; 230 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 231 | CLANG_WARN_UNREACHABLE_CODE = YES; 232 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 233 | CODE_SIGN_IDENTITY = "-"; 234 | COPY_PHASE_STRIP = NO; 235 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 236 | ENABLE_NS_ASSERTIONS = NO; 237 | ENABLE_STRICT_OBJC_MSGSEND = YES; 238 | GCC_C_LANGUAGE_STANDARD = gnu99; 239 | GCC_NO_COMMON_BLOCKS = YES; 240 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 241 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 242 | GCC_WARN_UNDECLARED_SELECTOR = YES; 243 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 244 | GCC_WARN_UNUSED_FUNCTION = YES; 245 | GCC_WARN_UNUSED_VARIABLE = YES; 246 | HEADER_SEARCH_PATHS = "$(SRCROOT)/../../include"; 247 | MACOSX_DEPLOYMENT_TARGET = 10.12; 248 | MTL_ENABLE_DEBUG_INFO = NO; 249 | SDKROOT = macosx; 250 | }; 251 | name = Release; 252 | }; 253 | 52EDA4701E90737E0088D4FA /* Debug */ = { 254 | isa = XCBuildConfiguration; 255 | buildSettings = { 256 | COMBINE_HIDPI_IMAGES = YES; 257 | HEADER_SEARCH_PATHS = "$(SRCROOT)/../include"; 258 | INFOPLIST_FILE = DOSComLoader/Info.plist; 259 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; 260 | PRODUCT_BUNDLE_IDENTIFIER = com.bjfn.DOSComLoader; 261 | PRODUCT_NAME = "$(TARGET_NAME)"; 262 | SKIP_INSTALL = YES; 263 | WRAPPER_EXTENSION = hopperLoader; 264 | }; 265 | name = Debug; 266 | }; 267 | 52EDA4711E90737E0088D4FA /* Release */ = { 268 | isa = XCBuildConfiguration; 269 | buildSettings = { 270 | COMBINE_HIDPI_IMAGES = YES; 271 | HEADER_SEARCH_PATHS = "$(SRCROOT)/../include"; 272 | INFOPLIST_FILE = DOSComLoader/Info.plist; 273 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; 274 | PRODUCT_BUNDLE_IDENTIFIER = com.bjfn.DOSComLoader; 275 | PRODUCT_NAME = "$(TARGET_NAME)"; 276 | SKIP_INSTALL = YES; 277 | WRAPPER_EXTENSION = hopperLoader; 278 | }; 279 | name = Release; 280 | }; 281 | /* End XCBuildConfiguration section */ 282 | 283 | /* Begin XCConfigurationList section */ 284 | 52EDA4641E90737E0088D4FA /* Build configuration list for PBXProject "DOSComLoader" */ = { 285 | isa = XCConfigurationList; 286 | buildConfigurations = ( 287 | 52EDA46D1E90737E0088D4FA /* Debug */, 288 | 52EDA46E1E90737E0088D4FA /* Release */, 289 | ); 290 | defaultConfigurationIsVisible = 0; 291 | defaultConfigurationName = Release; 292 | }; 293 | 52EDA46F1E90737E0088D4FA /* Build configuration list for PBXNativeTarget "DOSComLoader" */ = { 294 | isa = XCConfigurationList; 295 | buildConfigurations = ( 296 | 52EDA4701E90737E0088D4FA /* Debug */, 297 | 52EDA4711E90737E0088D4FA /* Release */, 298 | ); 299 | defaultConfigurationIsVisible = 0; 300 | defaultConfigurationName = Release; 301 | }; 302 | /* End XCConfigurationList section */ 303 | }; 304 | rootObject = 52EDA4611E90737E0088D4FA /* Project object */; 305 | } 306 | -------------------------------------------------------------------------------- /DOSComLoader/DOSComLoader/ComLoader.h: -------------------------------------------------------------------------------- 1 | // 2 | // ComLoader.h 3 | // HopperDos 4 | // 5 | // Created by john on 01.04.17. 6 | // Copyright © 2017 bjfn. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #define COM_SEGMENT @"DOS COM" 13 | 14 | @interface ComLoader : NSObject 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /DOSComLoader/DOSComLoader/ComLoader.m: -------------------------------------------------------------------------------- 1 | // 2 | // ComLoader.m 3 | // HopperDos 4 | // 5 | // Created by john on 01.04.17. 6 | // Copyright © 2017 bjfn. All rights reserved. 7 | // 8 | 9 | #import "ComLoader.h" 10 | 11 | @implementation ComLoader { 12 | NSObject *_services; 13 | } 14 | 15 | - (instancetype)initWithHopperServices:(NSObject *)services { 16 | if (self = [super init]) { 17 | _services = services; 18 | } 19 | return self; 20 | } 21 | 22 | - (NSObject*)pluginUUID { 23 | return [_services UUIDWithString:@"9f8d07d0-b9d4-4a96-8862-392ed8028cd6"]; 24 | } 25 | 26 | - (HopperPluginType)pluginType { 27 | return Plugin_Loader; 28 | } 29 | 30 | - (NSString *)pluginName { 31 | return @"DOS COM Loader"; 32 | } 33 | 34 | - (NSString *)pluginDescription { 35 | return @"DOS COM File Loader"; 36 | } 37 | 38 | - (NSString *)pluginAuthor { 39 | return @"bjohnfn@gmail.com"; 40 | } 41 | 42 | - (NSString *)pluginCopyright { 43 | return @"©2017 - bjohnfn@gmail.com"; 44 | } 45 | 46 | - (NSString *)pluginVersion { 47 | return @"0.0.1"; 48 | } 49 | 50 | - (nonnull NSString *)commandLineIdentifier { 51 | return @"DOSCom"; 52 | } 53 | 54 | 55 | + (int)sdkVersion { 56 | return HOPPER_CURRENT_SDK_VERSION; 57 | } 58 | 59 | 60 | - (CPUEndianess)endianess { 61 | return CPUEndianess_Little; 62 | } 63 | 64 | - (BOOL)canLoadDebugFiles { 65 | return NO; 66 | } 67 | 68 | // Returns an array of DetectedFileType objects. 69 | - (NSArray *)detectedTypesForData:(NSData *)data { 70 | if ([data length] < 1) return @[]; 71 | 72 | NSObject *type = [_services detectedType]; 73 | [type setFileDescription:@"DOS COM Executable"]; 74 | [type setAddressWidth:AW_16bits]; 75 | [type setCpuFamily:@"intel16"]; 76 | [type setCpuSubFamily:@"8086"]; 77 | [type setShortDescriptionString:@"dos_com"]; 78 | return @[type]; 79 | } 80 | 81 | - (void)fixupRebasedFile:(NSObject *)file withSlide:(int64_t)slide originalFileData:(NSData *)fileData { 82 | 83 | } 84 | 85 | - (FileLoaderLoadingStatus)loadDebugData:(NSData *)data forFile:(NSObject *)file usingCallback:(FileLoadingCallbackInfo)callback { 86 | return DIS_NotSupported; 87 | } 88 | 89 | - (NSData *)extractFromData:(NSData *)data usingDetectedFileType:(NSObject *)fileType returnAdjustOffset:(uint64_t *)adjustOffset { 90 | return nil; 91 | } 92 | 93 | 94 | - (FileLoaderLoadingStatus)loadData:(NSData *)data usingDetectedFileType:(NSObject *)fileType options:(FileLoaderOptions)options forFile:(NSObject *)file usingCallback:(FileLoadingCallbackInfo)callback { 95 | NSObject *segment = [file addSegmentAt:0x100 size:[data length]]; 96 | NSObject *section = [segment addSectionAt:0x100 size:[data length]]; 97 | 98 | segment.segmentName = COM_SEGMENT; 99 | section.sectionName = @"CODE"; 100 | section.containsCode = YES; 101 | 102 | segment.mappedData = data; 103 | segment.fileOffset = 0; 104 | segment.fileLength = [data length]; 105 | section.fileOffset = 0; 106 | section.fileLength = [data length]; 107 | 108 | 109 | file.cpuFamily = @"intel16"; 110 | file.cpuSubFamily = @"8086"; 111 | [file setAddressSpaceWidthInBits:16]; 112 | 113 | [file addEntryPoint:0x100]; 114 | 115 | return DIS_OK; 116 | } 117 | 118 | - (nullable NSArray *> *)detectedTypesForData:(nonnull NSData *)data ofFileNamed:(nullable NSString *)filename { 119 | return [self detectedTypesForData: data]; 120 | } 121 | 122 | 123 | - (nullable NSData *)extractFromData:(nonnull NSData *)data usingDetectedFileType:(nonnull NSObject *)fileType returnAdjustOffset:(nullable uint64_t *)adjustOffset returnAdjustFilename:(NSString *__autoreleasing _Nullable * _Nullable)newFilename { 124 | return nil; 125 | } 126 | 127 | 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /DOSComLoader/DOSComLoader/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | NSHumanReadableCopyright 22 | Copyright © 2017 bjfn. All rights reserved. 23 | NSPrincipalClass 24 | ComLoader 25 | 26 | 27 | -------------------------------------------------------------------------------- /DOSExeLoader/DOSExeLoader.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 52C64DE81E90F2F200E2E1AD /* MZLoader.mm in Sources */ = {isa = PBXBuildFile; fileRef = 52C64DE71E90F2F200E2E1AD /* MZLoader.mm */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXFileReference section */ 14 | 52C64DDD1E90F2CA00E2E1AD /* DOSExeLoader.hopperLoader */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DOSExeLoader.hopperLoader; sourceTree = BUILT_PRODUCTS_DIR; }; 15 | 52C64DE01E90F2CA00E2E1AD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 16 | 52C64DE61E90F2F200E2E1AD /* MZLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MZLoader.h; sourceTree = ""; }; 17 | 52C64DE71E90F2F200E2E1AD /* MZLoader.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MZLoader.mm; sourceTree = ""; }; 18 | 52C64DE91E91141000E2E1AD /* mz.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mz.h; sourceTree = ""; }; 19 | /* End PBXFileReference section */ 20 | 21 | /* Begin PBXFrameworksBuildPhase section */ 22 | 52C64DDA1E90F2CA00E2E1AD /* Frameworks */ = { 23 | isa = PBXFrameworksBuildPhase; 24 | buildActionMask = 2147483647; 25 | files = ( 26 | ); 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXFrameworksBuildPhase section */ 30 | 31 | /* Begin PBXGroup section */ 32 | 52C64DD41E90F2CA00E2E1AD = { 33 | isa = PBXGroup; 34 | children = ( 35 | 52C64DDF1E90F2CA00E2E1AD /* DOSExeLoader */, 36 | 52C64DDE1E90F2CA00E2E1AD /* Products */, 37 | ); 38 | sourceTree = ""; 39 | }; 40 | 52C64DDE1E90F2CA00E2E1AD /* Products */ = { 41 | isa = PBXGroup; 42 | children = ( 43 | 52C64DDD1E90F2CA00E2E1AD /* DOSExeLoader.hopperLoader */, 44 | ); 45 | name = Products; 46 | sourceTree = ""; 47 | }; 48 | 52C64DDF1E90F2CA00E2E1AD /* DOSExeLoader */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | 52C64DE01E90F2CA00E2E1AD /* Info.plist */, 52 | 52C64DE61E90F2F200E2E1AD /* MZLoader.h */, 53 | 52C64DE71E90F2F200E2E1AD /* MZLoader.mm */, 54 | 52C64DE91E91141000E2E1AD /* mz.h */, 55 | ); 56 | path = DOSExeLoader; 57 | sourceTree = ""; 58 | }; 59 | /* End PBXGroup section */ 60 | 61 | /* Begin PBXNativeTarget section */ 62 | 52C64DDC1E90F2CA00E2E1AD /* DOSExeLoader */ = { 63 | isa = PBXNativeTarget; 64 | buildConfigurationList = 52C64DE31E90F2CA00E2E1AD /* Build configuration list for PBXNativeTarget "DOSExeLoader" */; 65 | buildPhases = ( 66 | 52C64DD91E90F2CA00E2E1AD /* Sources */, 67 | 52C64DDA1E90F2CA00E2E1AD /* Frameworks */, 68 | 52C64DDB1E90F2CA00E2E1AD /* Resources */, 69 | ); 70 | buildRules = ( 71 | ); 72 | dependencies = ( 73 | ); 74 | name = DOSExeLoader; 75 | productName = DOSExeLoader; 76 | productReference = 52C64DDD1E90F2CA00E2E1AD /* DOSExeLoader.hopperLoader */; 77 | productType = "com.apple.product-type.bundle"; 78 | }; 79 | /* End PBXNativeTarget section */ 80 | 81 | /* Begin PBXProject section */ 82 | 52C64DD51E90F2CA00E2E1AD /* Project object */ = { 83 | isa = PBXProject; 84 | attributes = { 85 | LastUpgradeCheck = 1030; 86 | ORGANIZATIONNAME = bjfn; 87 | TargetAttributes = { 88 | 52C64DDC1E90F2CA00E2E1AD = { 89 | CreatedOnToolsVersion = 8.3; 90 | ProvisioningStyle = Automatic; 91 | }; 92 | }; 93 | }; 94 | buildConfigurationList = 52C64DD81E90F2CA00E2E1AD /* Build configuration list for PBXProject "DOSExeLoader" */; 95 | compatibilityVersion = "Xcode 3.2"; 96 | developmentRegion = English; 97 | hasScannedForEncodings = 0; 98 | knownRegions = ( 99 | English, 100 | en, 101 | ); 102 | mainGroup = 52C64DD41E90F2CA00E2E1AD; 103 | productRefGroup = 52C64DDE1E90F2CA00E2E1AD /* Products */; 104 | projectDirPath = ""; 105 | projectRoot = ""; 106 | targets = ( 107 | 52C64DDC1E90F2CA00E2E1AD /* DOSExeLoader */, 108 | ); 109 | }; 110 | /* End PBXProject section */ 111 | 112 | /* Begin PBXResourcesBuildPhase section */ 113 | 52C64DDB1E90F2CA00E2E1AD /* Resources */ = { 114 | isa = PBXResourcesBuildPhase; 115 | buildActionMask = 2147483647; 116 | files = ( 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | /* End PBXResourcesBuildPhase section */ 121 | 122 | /* Begin PBXSourcesBuildPhase section */ 123 | 52C64DD91E90F2CA00E2E1AD /* Sources */ = { 124 | isa = PBXSourcesBuildPhase; 125 | buildActionMask = 2147483647; 126 | files = ( 127 | 52C64DE81E90F2F200E2E1AD /* MZLoader.mm in Sources */, 128 | ); 129 | runOnlyForDeploymentPostprocessing = 0; 130 | }; 131 | /* End PBXSourcesBuildPhase section */ 132 | 133 | /* Begin XCBuildConfiguration section */ 134 | 52C64DE11E90F2CA00E2E1AD /* Debug */ = { 135 | isa = XCBuildConfiguration; 136 | buildSettings = { 137 | ALWAYS_SEARCH_USER_PATHS = NO; 138 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 139 | CLANG_ANALYZER_NONNULL = YES; 140 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 141 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 142 | CLANG_CXX_LIBRARY = "libc++"; 143 | CLANG_ENABLE_MODULES = YES; 144 | CLANG_ENABLE_OBJC_ARC = YES; 145 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 146 | CLANG_WARN_BOOL_CONVERSION = YES; 147 | CLANG_WARN_COMMA = YES; 148 | CLANG_WARN_CONSTANT_CONVERSION = YES; 149 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 150 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 151 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 152 | CLANG_WARN_EMPTY_BODY = YES; 153 | CLANG_WARN_ENUM_CONVERSION = YES; 154 | CLANG_WARN_INFINITE_RECURSION = YES; 155 | CLANG_WARN_INT_CONVERSION = YES; 156 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 157 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 158 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 159 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 160 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 161 | CLANG_WARN_STRICT_PROTOTYPES = YES; 162 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 163 | CLANG_WARN_UNREACHABLE_CODE = YES; 164 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 165 | CODE_SIGN_IDENTITY = "-"; 166 | COPY_PHASE_STRIP = NO; 167 | DEBUG_INFORMATION_FORMAT = dwarf; 168 | ENABLE_STRICT_OBJC_MSGSEND = YES; 169 | ENABLE_TESTABILITY = YES; 170 | GCC_C_LANGUAGE_STANDARD = gnu99; 171 | GCC_DYNAMIC_NO_PIC = NO; 172 | GCC_NO_COMMON_BLOCKS = YES; 173 | GCC_OPTIMIZATION_LEVEL = 0; 174 | GCC_PREPROCESSOR_DEFINITIONS = ( 175 | "DEBUG=1", 176 | "$(inherited)", 177 | ); 178 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 179 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 180 | GCC_WARN_UNDECLARED_SELECTOR = YES; 181 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 182 | GCC_WARN_UNUSED_FUNCTION = YES; 183 | GCC_WARN_UNUSED_VARIABLE = YES; 184 | MACOSX_DEPLOYMENT_TARGET = 10.12; 185 | MTL_ENABLE_DEBUG_INFO = YES; 186 | ONLY_ACTIVE_ARCH = YES; 187 | SDKROOT = macosx; 188 | }; 189 | name = Debug; 190 | }; 191 | 52C64DE21E90F2CA00E2E1AD /* Release */ = { 192 | isa = XCBuildConfiguration; 193 | buildSettings = { 194 | ALWAYS_SEARCH_USER_PATHS = NO; 195 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 196 | CLANG_ANALYZER_NONNULL = YES; 197 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 198 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 199 | CLANG_CXX_LIBRARY = "libc++"; 200 | CLANG_ENABLE_MODULES = YES; 201 | CLANG_ENABLE_OBJC_ARC = YES; 202 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 203 | CLANG_WARN_BOOL_CONVERSION = YES; 204 | CLANG_WARN_COMMA = YES; 205 | CLANG_WARN_CONSTANT_CONVERSION = YES; 206 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 207 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 208 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 209 | CLANG_WARN_EMPTY_BODY = YES; 210 | CLANG_WARN_ENUM_CONVERSION = YES; 211 | CLANG_WARN_INFINITE_RECURSION = YES; 212 | CLANG_WARN_INT_CONVERSION = YES; 213 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 214 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 215 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 216 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 217 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 218 | CLANG_WARN_STRICT_PROTOTYPES = YES; 219 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 220 | CLANG_WARN_UNREACHABLE_CODE = YES; 221 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 222 | CODE_SIGN_IDENTITY = "-"; 223 | COPY_PHASE_STRIP = NO; 224 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 225 | ENABLE_NS_ASSERTIONS = NO; 226 | ENABLE_STRICT_OBJC_MSGSEND = YES; 227 | GCC_C_LANGUAGE_STANDARD = gnu99; 228 | GCC_NO_COMMON_BLOCKS = YES; 229 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 230 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 231 | GCC_WARN_UNDECLARED_SELECTOR = YES; 232 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 233 | GCC_WARN_UNUSED_FUNCTION = YES; 234 | GCC_WARN_UNUSED_VARIABLE = YES; 235 | MACOSX_DEPLOYMENT_TARGET = 10.12; 236 | MTL_ENABLE_DEBUG_INFO = NO; 237 | SDKROOT = macosx; 238 | }; 239 | name = Release; 240 | }; 241 | 52C64DE41E90F2CA00E2E1AD /* Debug */ = { 242 | isa = XCBuildConfiguration; 243 | buildSettings = { 244 | COMBINE_HIDPI_IMAGES = YES; 245 | HEADER_SEARCH_PATHS = "$(SRCROOT)/../include"; 246 | INFOPLIST_FILE = DOSExeLoader/Info.plist; 247 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; 248 | PRODUCT_BUNDLE_IDENTIFIER = com.bjfn.DOSExeLoader; 249 | PRODUCT_NAME = "$(TARGET_NAME)"; 250 | SKIP_INSTALL = YES; 251 | WRAPPER_EXTENSION = hopperLoader; 252 | }; 253 | name = Debug; 254 | }; 255 | 52C64DE51E90F2CA00E2E1AD /* Release */ = { 256 | isa = XCBuildConfiguration; 257 | buildSettings = { 258 | COMBINE_HIDPI_IMAGES = YES; 259 | HEADER_SEARCH_PATHS = "$(SRCROOT)/../include"; 260 | INFOPLIST_FILE = DOSExeLoader/Info.plist; 261 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; 262 | PRODUCT_BUNDLE_IDENTIFIER = com.bjfn.DOSExeLoader; 263 | PRODUCT_NAME = "$(TARGET_NAME)"; 264 | SKIP_INSTALL = YES; 265 | WRAPPER_EXTENSION = hopperLoader; 266 | }; 267 | name = Release; 268 | }; 269 | /* End XCBuildConfiguration section */ 270 | 271 | /* Begin XCConfigurationList section */ 272 | 52C64DD81E90F2CA00E2E1AD /* Build configuration list for PBXProject "DOSExeLoader" */ = { 273 | isa = XCConfigurationList; 274 | buildConfigurations = ( 275 | 52C64DE11E90F2CA00E2E1AD /* Debug */, 276 | 52C64DE21E90F2CA00E2E1AD /* Release */, 277 | ); 278 | defaultConfigurationIsVisible = 0; 279 | defaultConfigurationName = Release; 280 | }; 281 | 52C64DE31E90F2CA00E2E1AD /* Build configuration list for PBXNativeTarget "DOSExeLoader" */ = { 282 | isa = XCConfigurationList; 283 | buildConfigurations = ( 284 | 52C64DE41E90F2CA00E2E1AD /* Debug */, 285 | 52C64DE51E90F2CA00E2E1AD /* Release */, 286 | ); 287 | defaultConfigurationIsVisible = 0; 288 | defaultConfigurationName = Release; 289 | }; 290 | /* End XCConfigurationList section */ 291 | }; 292 | rootObject = 52C64DD51E90F2CA00E2E1AD /* Project object */; 293 | } 294 | -------------------------------------------------------------------------------- /DOSExeLoader/DOSExeLoader/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | NSHumanReadableCopyright 22 | Copyright © 2017 bjfn. All rights reserved. 23 | NSPrincipalClass 24 | MZLoader 25 | 26 | 27 | -------------------------------------------------------------------------------- /DOSExeLoader/DOSExeLoader/MZLoader.h: -------------------------------------------------------------------------------- 1 | // 2 | // MZLoader.h 3 | // DOSExeLoader 4 | // 5 | // Created by john on 02.04.17. 6 | // Copyright © 2017 bjfn. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface MZLoader : NSObject 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /DOSExeLoader/DOSExeLoader/MZLoader.mm: -------------------------------------------------------------------------------- 1 | // 2 | // MZLoader.m 3 | // DOSExeLoader 4 | // 5 | // Created by john on 02.04.17. 6 | // Copyright © 2017 bjfn. All rights reserved. 7 | // 8 | 9 | #import "MZLoader.h" 10 | #include "mz.h" 11 | #include 12 | using namespace std; 13 | 14 | #define FAR_JMP 0xEA 15 | #define FAR_CALL 0x9A 16 | #define IS_FARJC(OP) (OP==FAR_JMP || OP==FAR_CALL) 17 | #define IRET 0xCF 18 | #define NRET 0xC3 19 | #define FRET 0xCB 20 | #define IS_RET(OP) (OP==IRET || OP==NRET || OP==FRET) 21 | #define NPRET 0xC2 22 | #define FPRET 0xCA 23 | #define IS_PRET(OP) (OP==NPRET || OP==FPRET) 24 | 25 | @implementation MZLoader{ 26 | NSObject *_services; 27 | } 28 | 29 | - (instancetype)initWithHopperServices:(NSObject *)services { 30 | if (self = [super init]) { 31 | _services = services; 32 | } 33 | return self; 34 | } 35 | 36 | - (nonnull NSObject *)pluginUUID { 37 | return [_services UUIDWithString:@"1a56d108-f990-478b-8b0b-f026973a2651"]; 38 | } 39 | 40 | - (HopperPluginType)pluginType { 41 | return Plugin_Loader; 42 | } 43 | 44 | - (NSString *)pluginName { 45 | return @"DOS MZ Loader"; 46 | } 47 | 48 | - (NSString *)pluginDescription { 49 | return @"DOS MZ File Loader"; 50 | } 51 | 52 | - (NSString *)pluginAuthor { 53 | return @"bjohnfn@gmail.com"; 54 | } 55 | 56 | - (NSString *)pluginCopyright { 57 | return @"©2017 - bjohnfn@gmail.com"; 58 | } 59 | 60 | - (NSString *)pluginVersion { 61 | return @"0.0.1"; 62 | } 63 | 64 | - (nonnull NSString *)commandLineIdentifier { 65 | return @"DOSExe"; 66 | } 67 | 68 | 69 | + (int)sdkVersion { 70 | return HOPPER_CURRENT_SDK_VERSION; 71 | } 72 | 73 | 74 | - (CPUEndianess)endianess { 75 | return CPUEndianess_Little; 76 | } 77 | 78 | - (BOOL)canLoadDebugFiles { 79 | return NO; 80 | } 81 | 82 | // Returns an array of DetectedFileType objects. 83 | - (NSArray *)detectedTypesForData:(NSData *)data { 84 | if ([data length] < sizeof(MZHeader)) 85 | return @[]; 86 | 87 | const void *bytes = (const void *)[data bytes]; 88 | MZHeader *mz=(MZHeader*)bytes; 89 | if (mz->signature!=MZ_MAGIC){ 90 | return @[]; 91 | } 92 | 93 | NSObject *type = [_services detectedType]; 94 | [type setFileDescription:@"DOS MZ Executable"]; 95 | [type setAddressWidth:AW_16bits]; 96 | [type setCpuFamily:@"intel16"]; 97 | [type setCpuSubFamily:@"8086"]; 98 | [type setShortDescriptionString:@"dos_mz"]; 99 | return @[type]; 100 | } 101 | 102 | - (void)fixupRebasedFile:(NSObject *)file withSlide:(int64_t)slide originalFileData:(NSData *)fileData { 103 | 104 | } 105 | 106 | - (FileLoaderLoadingStatus)loadDebugData:(NSData *)data forFile:(NSObject *)file usingCallback:(FileLoadingCallbackInfo)callback { 107 | return DIS_NotSupported; 108 | } 109 | 110 | - (NSData *)extractFromData:(NSData *)data usingDetectedFileType:(NSObject *)fileType returnAdjustOffset:(uint64_t *)adjustOffset { 111 | return nil; 112 | } 113 | 114 | 115 | - (FileLoaderLoadingStatus)loadData:(NSData *)data usingDetectedFileType:(NSObject *)fileType options:(FileLoaderOptions)options forFile:(NSObject *)file usingCallback:(FileLoadingCallbackInfo)callback { 116 | 117 | const unsigned char *bytes = (const unsigned char *)[data bytes]; 118 | MZHeader* mz = (MZHeader*)bytes; 119 | uint codeofs = mz->header_paragraphs * MZ_PARA; 120 | uint exesz = mz->blocks_in_file * MZ_BLOCK; 121 | if (mz->bytes_in_last_block){ 122 | exesz -= MZ_BLOCK - mz->bytes_in_last_block; 123 | } 124 | uint codesz = exesz - codeofs; 125 | 126 | map segs; 127 | segs[0] = false; 128 | segs[mz->cs] = true; 129 | 130 | MZReloc *reloc = (MZReloc*)(bytes + mz->reloc_table_offset); 131 | for (int i=0; inum_relocs; i++){ 132 | uint ofs = codeofs + (reloc->segment << 4) + reloc->offset; 133 | if (!segs.count(reloc->segment)){ 134 | segs[reloc->segment] = false; 135 | } 136 | uint8_t* op = (uint8_t*)(bytes + ofs - 3); // check far call/jmp bytes - OP OFFS SEGM 137 | ushort rval = *(ushort*)(op+3); 138 | if ([data length] > codeofs+(rval << 4)){ 139 | segs[rval] |= IS_FARJC(*op); 140 | } 141 | reloc++; 142 | } 143 | 144 | NSObject *segment = [file addSegmentAt:0 size:codesz]; 145 | segment.segmentName = @"DOS EXE"; 146 | segment.mappedData = [NSData dataWithBytes:bytes+codeofs length:codesz]; 147 | segment.fileOffset = codeofs; 148 | segment.fileLength = codesz; 149 | 150 | uint32 max = segs.rbegin()->first << 4; 151 | uint32 ofs=0; 152 | for (auto it=segs.begin(); it!=segs.end(); ++it){ 153 | map::iterator prev; 154 | if (it == segs.begin()){ 155 | prev = it; 156 | continue; 157 | } 158 | 159 | uint32 end = 0; 160 | do{ 161 | uint start = (prev->first << 4)+ofs; 162 | end = start==max+ofs ? codesz : it->first << 4; 163 | //tune seg end to ret opcode 164 | if (it->second && prev->second){ // both code sections 165 | uint8_t *op = (uint8_t*)(bytes + codeofs + end -3); //3 bytes for stack pop RET 166 | for (ofs=0; ofs<2 && !IS_PRET(*op); ++ofs) ++op; 167 | if (ofs>1){ 168 | for (ofs=0; ofs<16 && !IS_RET(*op) && !IS_PRET(*op); ++ofs) ++op; 169 | if (ofs>15){ 170 | //ret not found 171 | ofs=0; 172 | }else if (IS_PRET(*op)){ 173 | ofs+=2; 174 | } 175 | } 176 | end += ofs; 177 | }else{ 178 | ofs=0; 179 | } 180 | size_t sz = end - start; 181 | NSLog(@"found segment %08X-%08X", start, end); 182 | 183 | NSObject *section = [segment addSectionAt:start size:sz]; 184 | 185 | if (prev->second){ 186 | section.sectionName = [NSString stringWithFormat:@"%04X:%04X CODE", prev->first, start-(prev->first << 4)]; 187 | section.pureCodeSection = NO; 188 | section.containsCode = YES; 189 | }else{ 190 | section.sectionName = [NSString stringWithFormat:@"%04X:%04X DATA", prev->first, start-(prev->first << 4)]; 191 | section.pureDataSection = YES; 192 | section.containsCode = NO; 193 | 194 | } 195 | section.fileOffset = codeofs + start; 196 | section.fileLength = sz; 197 | 198 | prev=it; 199 | 200 | }while(end == max+ofs); 201 | } 202 | 203 | //add stack segment 204 | segment = [file addSegmentAt:[data length] size:(mz->ss<<4)+mz->sp - [data length]]; 205 | segment.segmentName = @"DOS STACK"; 206 | 207 | /* 208 | NSObject *section = [segment addSectionAt:0 size:mz->sp]; 209 | section.sectionName = [NSString stringWithFormat:@"%04X:%04X STACK", mz->ss, 0]; 210 | section.pureDataSection = YES; 211 | section.containsCode = NO; 212 | */ 213 | 214 | 215 | file.cpuFamily = @"intel16"; 216 | file.cpuSubFamily = @"8086"; 217 | [file setAddressSpaceWidthInBits:16]; 218 | 219 | NSLog(@"Entry point at 0x%4.4X:0x%4.4X", mz->cs, mz->ip); 220 | [file addEntryPoint: mz->cs * MZ_PARA + mz->ip]; 221 | 222 | return DIS_OK; 223 | } 224 | 225 | - (nullable NSArray *> *)detectedTypesForData:(nonnull NSData *)data ofFileNamed:(nullable NSString *)filename { 226 | return [self detectedTypesForData: data]; 227 | } 228 | 229 | 230 | - (nullable NSData *)extractFromData:(nonnull NSData *)data usingDetectedFileType:(nonnull NSObject *)fileType returnAdjustOffset:(nullable uint64_t *)adjustOffset returnAdjustFilename:(NSString *__autoreleasing _Nullable * _Nullable)newFilename { 231 | return nil; 232 | } 233 | 234 | 235 | 236 | @end 237 | -------------------------------------------------------------------------------- /DOSExeLoader/DOSExeLoader/mz.h: -------------------------------------------------------------------------------- 1 | // 2 | // mz.h 3 | // DOSExeLoader 4 | // 5 | // Created by john on 02.04.17. 6 | // Copyright © 2017 bjfn. All rights reserved. 7 | // 8 | 9 | #ifndef mz_h 10 | #define mz_h 11 | 12 | #define MZ_MAGIC 0x5A4D 13 | #define MZ_BLOCK 0x200 14 | #define MZ_PARA 0x10 15 | 16 | struct MZHeader{ 17 | unsigned short signature; 18 | unsigned short bytes_in_last_block; 19 | unsigned short blocks_in_file; 20 | unsigned short num_relocs; 21 | unsigned short header_paragraphs; 22 | unsigned short min_extra_paragraphs; 23 | unsigned short max_extra_paragraphs; 24 | unsigned short ss; 25 | unsigned short sp; 26 | unsigned short checksum; 27 | unsigned short ip; 28 | unsigned short cs; 29 | unsigned short reloc_table_offset; 30 | unsigned short overlay_number; 31 | }; 32 | 33 | struct MZReloc{ 34 | unsigned short offset; 35 | unsigned short segment; 36 | }; 37 | 38 | #endif /* mz_h */ 39 | -------------------------------------------------------------------------------- /HopperDos.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Intel16CPU/Intel16CPU.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 523980691F233D53002B2993 /* ints.json in Resources */ = {isa = PBXBuildFile; fileRef = 523980671F233D53002B2993 /* ints.json */; }; 11 | 5239806A1F233D53002B2993 /* ports.json in Resources */ = {isa = PBXBuildFile; fileRef = 523980681F233D53002B2993 /* ports.json */; }; 12 | 5239806E1F235B84002B2993 /* OpComment.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5239806D1F235B84002B2993 /* OpComment.mm */; }; 13 | 523E54BB1E904344007D2654 /* Intel16CPU.mm in Sources */ = {isa = PBXBuildFile; fileRef = 523E54BA1E904344007D2654 /* Intel16CPU.mm */; }; 14 | 523E54BE1E9044A6007D2654 /* Intel16Ctx.m in Sources */ = {isa = PBXBuildFile; fileRef = 523E54BD1E9044A6007D2654 /* Intel16Ctx.m */; }; 15 | 523E54C11E9044DD007D2654 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523E54C01E9044DD007D2654 /* CoreFoundation.framework */; }; 16 | 52AC8A511F251696003B58E1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52AC8A501F251696003B58E1 /* Foundation.framework */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 523980671F233D53002B2993 /* ints.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = ints.json; path = Intel16CPU/ints.json; sourceTree = ""; }; 21 | 523980681F233D53002B2993 /* ports.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = ports.json; path = Intel16CPU/ports.json; sourceTree = ""; }; 22 | 5239806C1F235B84002B2993 /* OpComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpComment.h; sourceTree = ""; }; 23 | 5239806D1F235B84002B2993 /* OpComment.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OpComment.mm; sourceTree = ""; }; 24 | 523E54B01E90431E007D2654 /* Intel16CPU.hopperCPU */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Intel16CPU.hopperCPU; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | 523E54B31E90431E007D2654 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 26 | 523E54B91E904344007D2654 /* Intel16CPU.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Intel16CPU.h; sourceTree = ""; }; 27 | 523E54BA1E904344007D2654 /* Intel16CPU.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Intel16CPU.mm; sourceTree = ""; }; 28 | 523E54BC1E9044A6007D2654 /* Intel16Ctx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Intel16Ctx.h; sourceTree = ""; }; 29 | 523E54BD1E9044A6007D2654 /* Intel16Ctx.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Intel16Ctx.m; sourceTree = ""; }; 30 | 523E54C01E9044DD007D2654 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; 31 | 52AC8A501F251696003B58E1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 32 | /* End PBXFileReference section */ 33 | 34 | /* Begin PBXFrameworksBuildPhase section */ 35 | 523E54AD1E90431E007D2654 /* Frameworks */ = { 36 | isa = PBXFrameworksBuildPhase; 37 | buildActionMask = 2147483647; 38 | files = ( 39 | 52AC8A511F251696003B58E1 /* Foundation.framework in Frameworks */, 40 | 523E54C11E9044DD007D2654 /* CoreFoundation.framework in Frameworks */, 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 5239806B1F233D58002B2993 /* Resources */ = { 48 | isa = PBXGroup; 49 | children = ( 50 | 523980671F233D53002B2993 /* ints.json */, 51 | 523980681F233D53002B2993 /* ports.json */, 52 | ); 53 | name = Resources; 54 | sourceTree = ""; 55 | }; 56 | 523E54A71E90431E007D2654 = { 57 | isa = PBXGroup; 58 | children = ( 59 | 5239806B1F233D58002B2993 /* Resources */, 60 | 523E54B21E90431E007D2654 /* Intel16CPU */, 61 | 523E54B11E90431E007D2654 /* Products */, 62 | 523E54BF1E9044DD007D2654 /* Frameworks */, 63 | ); 64 | sourceTree = ""; 65 | }; 66 | 523E54B11E90431E007D2654 /* Products */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | 523E54B01E90431E007D2654 /* Intel16CPU.hopperCPU */, 70 | ); 71 | name = Products; 72 | sourceTree = ""; 73 | }; 74 | 523E54B21E90431E007D2654 /* Intel16CPU */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 523E54B31E90431E007D2654 /* Info.plist */, 78 | 523E54B91E904344007D2654 /* Intel16CPU.h */, 79 | 523E54BA1E904344007D2654 /* Intel16CPU.mm */, 80 | 523E54BC1E9044A6007D2654 /* Intel16Ctx.h */, 81 | 523E54BD1E9044A6007D2654 /* Intel16Ctx.m */, 82 | 5239806C1F235B84002B2993 /* OpComment.h */, 83 | 5239806D1F235B84002B2993 /* OpComment.mm */, 84 | ); 85 | path = Intel16CPU; 86 | sourceTree = ""; 87 | }; 88 | 523E54BF1E9044DD007D2654 /* Frameworks */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 52AC8A501F251696003B58E1 /* Foundation.framework */, 92 | 523E54C01E9044DD007D2654 /* CoreFoundation.framework */, 93 | ); 94 | name = Frameworks; 95 | sourceTree = ""; 96 | }; 97 | /* End PBXGroup section */ 98 | 99 | /* Begin PBXNativeTarget section */ 100 | 523E54AF1E90431E007D2654 /* Intel16CPU */ = { 101 | isa = PBXNativeTarget; 102 | buildConfigurationList = 523E54B61E90431E007D2654 /* Build configuration list for PBXNativeTarget "Intel16CPU" */; 103 | buildPhases = ( 104 | 523E54AC1E90431E007D2654 /* Sources */, 105 | 523E54AD1E90431E007D2654 /* Frameworks */, 106 | 523E54AE1E90431E007D2654 /* Resources */, 107 | ); 108 | buildRules = ( 109 | ); 110 | dependencies = ( 111 | ); 112 | name = Intel16CPU; 113 | productName = Intel16CPU; 114 | productReference = 523E54B01E90431E007D2654 /* Intel16CPU.hopperCPU */; 115 | productType = "com.apple.product-type.bundle"; 116 | }; 117 | /* End PBXNativeTarget section */ 118 | 119 | /* Begin PBXProject section */ 120 | 523E54A81E90431E007D2654 /* Project object */ = { 121 | isa = PBXProject; 122 | attributes = { 123 | LastUpgradeCheck = 1030; 124 | ORGANIZATIONNAME = bjfn; 125 | TargetAttributes = { 126 | 523E54AF1E90431E007D2654 = { 127 | CreatedOnToolsVersion = 8.3; 128 | ProvisioningStyle = Automatic; 129 | }; 130 | }; 131 | }; 132 | buildConfigurationList = 523E54AB1E90431E007D2654 /* Build configuration list for PBXProject "Intel16CPU" */; 133 | compatibilityVersion = "Xcode 3.2"; 134 | developmentRegion = English; 135 | hasScannedForEncodings = 0; 136 | knownRegions = ( 137 | English, 138 | en, 139 | ); 140 | mainGroup = 523E54A71E90431E007D2654; 141 | productRefGroup = 523E54B11E90431E007D2654 /* Products */; 142 | projectDirPath = ""; 143 | projectRoot = ""; 144 | targets = ( 145 | 523E54AF1E90431E007D2654 /* Intel16CPU */, 146 | ); 147 | }; 148 | /* End PBXProject section */ 149 | 150 | /* Begin PBXResourcesBuildPhase section */ 151 | 523E54AE1E90431E007D2654 /* Resources */ = { 152 | isa = PBXResourcesBuildPhase; 153 | buildActionMask = 2147483647; 154 | files = ( 155 | 5239806A1F233D53002B2993 /* ports.json in Resources */, 156 | 523980691F233D53002B2993 /* ints.json in Resources */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXResourcesBuildPhase section */ 161 | 162 | /* Begin PBXSourcesBuildPhase section */ 163 | 523E54AC1E90431E007D2654 /* Sources */ = { 164 | isa = PBXSourcesBuildPhase; 165 | buildActionMask = 2147483647; 166 | files = ( 167 | 523E54BB1E904344007D2654 /* Intel16CPU.mm in Sources */, 168 | 523E54BE1E9044A6007D2654 /* Intel16Ctx.m in Sources */, 169 | 5239806E1F235B84002B2993 /* OpComment.mm in Sources */, 170 | ); 171 | runOnlyForDeploymentPostprocessing = 0; 172 | }; 173 | /* End PBXSourcesBuildPhase section */ 174 | 175 | /* Begin XCBuildConfiguration section */ 176 | 523E54B41E90431E007D2654 /* Debug */ = { 177 | isa = XCBuildConfiguration; 178 | buildSettings = { 179 | ALWAYS_SEARCH_USER_PATHS = NO; 180 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 181 | CLANG_ANALYZER_NONNULL = YES; 182 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 183 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 184 | CLANG_CXX_LIBRARY = "libc++"; 185 | CLANG_ENABLE_MODULES = YES; 186 | CLANG_ENABLE_OBJC_ARC = YES; 187 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 188 | CLANG_WARN_BOOL_CONVERSION = YES; 189 | CLANG_WARN_COMMA = YES; 190 | CLANG_WARN_CONSTANT_CONVERSION = YES; 191 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 192 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 193 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 194 | CLANG_WARN_EMPTY_BODY = YES; 195 | CLANG_WARN_ENUM_CONVERSION = YES; 196 | CLANG_WARN_INFINITE_RECURSION = YES; 197 | CLANG_WARN_INT_CONVERSION = YES; 198 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 199 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 200 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 201 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 202 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 203 | CLANG_WARN_STRICT_PROTOTYPES = YES; 204 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 205 | CLANG_WARN_UNREACHABLE_CODE = YES; 206 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 207 | CODE_SIGN_IDENTITY = "-"; 208 | COPY_PHASE_STRIP = NO; 209 | DEBUG_INFORMATION_FORMAT = dwarf; 210 | ENABLE_STRICT_OBJC_MSGSEND = YES; 211 | ENABLE_TESTABILITY = YES; 212 | GCC_C_LANGUAGE_STANDARD = gnu99; 213 | GCC_DYNAMIC_NO_PIC = NO; 214 | GCC_NO_COMMON_BLOCKS = YES; 215 | GCC_OPTIMIZATION_LEVEL = 0; 216 | GCC_PREPROCESSOR_DEFINITIONS = ( 217 | "DEBUG=1", 218 | "$(inherited)", 219 | ); 220 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 221 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 222 | GCC_WARN_UNDECLARED_SELECTOR = YES; 223 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 224 | GCC_WARN_UNUSED_FUNCTION = YES; 225 | GCC_WARN_UNUSED_VARIABLE = YES; 226 | LIBRARY_SEARCH_PATHS = "$(SRCROOT)/../../lib"; 227 | MACOSX_DEPLOYMENT_TARGET = 10.12; 228 | MTL_ENABLE_DEBUG_INFO = YES; 229 | ONLY_ACTIVE_ARCH = YES; 230 | SDKROOT = macosx; 231 | SYSTEM_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../include"; 232 | }; 233 | name = Debug; 234 | }; 235 | 523E54B51E90431E007D2654 /* Release */ = { 236 | isa = XCBuildConfiguration; 237 | buildSettings = { 238 | ALWAYS_SEARCH_USER_PATHS = NO; 239 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 240 | CLANG_ANALYZER_NONNULL = YES; 241 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 242 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 243 | CLANG_CXX_LIBRARY = "libc++"; 244 | CLANG_ENABLE_MODULES = YES; 245 | CLANG_ENABLE_OBJC_ARC = YES; 246 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 247 | CLANG_WARN_BOOL_CONVERSION = YES; 248 | CLANG_WARN_COMMA = YES; 249 | CLANG_WARN_CONSTANT_CONVERSION = YES; 250 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 251 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 252 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 253 | CLANG_WARN_EMPTY_BODY = YES; 254 | CLANG_WARN_ENUM_CONVERSION = YES; 255 | CLANG_WARN_INFINITE_RECURSION = YES; 256 | CLANG_WARN_INT_CONVERSION = YES; 257 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 258 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 259 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 260 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 261 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 262 | CLANG_WARN_STRICT_PROTOTYPES = YES; 263 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 264 | CLANG_WARN_UNREACHABLE_CODE = YES; 265 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 266 | CODE_SIGN_IDENTITY = "-"; 267 | COPY_PHASE_STRIP = NO; 268 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 269 | ENABLE_NS_ASSERTIONS = NO; 270 | ENABLE_STRICT_OBJC_MSGSEND = YES; 271 | GCC_C_LANGUAGE_STANDARD = gnu99; 272 | GCC_NO_COMMON_BLOCKS = YES; 273 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 274 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 275 | GCC_WARN_UNDECLARED_SELECTOR = YES; 276 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 277 | GCC_WARN_UNUSED_FUNCTION = YES; 278 | GCC_WARN_UNUSED_VARIABLE = YES; 279 | LIBRARY_SEARCH_PATHS = "$(SRCROOT)/../../lib"; 280 | MACOSX_DEPLOYMENT_TARGET = 10.12; 281 | MTL_ENABLE_DEBUG_INFO = NO; 282 | SDKROOT = macosx; 283 | SYSTEM_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../include"; 284 | }; 285 | name = Release; 286 | }; 287 | 523E54B71E90431E007D2654 /* Debug */ = { 288 | isa = XCBuildConfiguration; 289 | buildSettings = { 290 | COMBINE_HIDPI_IMAGES = YES; 291 | HEADER_SEARCH_PATHS = ( 292 | "$(SRCROOT)/../include", 293 | /usr/local/Cellar/capstone/4.0.1/include/, 294 | ); 295 | INFOPLIST_FILE = Intel16CPU/Info.plist; 296 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; 297 | LIBRARY_SEARCH_PATHS = /usr/local/Cellar/capstone/4.0.1/lib; 298 | MACOSX_DEPLOYMENT_TARGET = 10.14; 299 | OTHER_LDFLAGS = /usr/local/Cellar/capstone/4.0.1/lib/libcapstone.a; 300 | PRODUCT_BUNDLE_IDENTIFIER = com.bjfn.Intel16CPU; 301 | PRODUCT_NAME = "$(TARGET_NAME)"; 302 | SKIP_INSTALL = YES; 303 | WRAPPER_EXTENSION = hopperCPU; 304 | }; 305 | name = Debug; 306 | }; 307 | 523E54B81E90431E007D2654 /* Release */ = { 308 | isa = XCBuildConfiguration; 309 | buildSettings = { 310 | COMBINE_HIDPI_IMAGES = YES; 311 | HEADER_SEARCH_PATHS = ( 312 | "$(SRCROOT)/../include", 313 | /usr/local/Cellar/capstone/4.0.1/include/, 314 | ); 315 | INFOPLIST_FILE = Intel16CPU/Info.plist; 316 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; 317 | LIBRARY_SEARCH_PATHS = /usr/local/Cellar/capstone/4.0.1/lib; 318 | MACOSX_DEPLOYMENT_TARGET = 10.14; 319 | OTHER_LDFLAGS = /usr/local/Cellar/capstone/4.0.1/lib/libcapstone.a; 320 | PRODUCT_BUNDLE_IDENTIFIER = com.bjfn.Intel16CPU; 321 | PRODUCT_NAME = "$(TARGET_NAME)"; 322 | SKIP_INSTALL = YES; 323 | WRAPPER_EXTENSION = hopperCPU; 324 | }; 325 | name = Release; 326 | }; 327 | /* End XCBuildConfiguration section */ 328 | 329 | /* Begin XCConfigurationList section */ 330 | 523E54AB1E90431E007D2654 /* Build configuration list for PBXProject "Intel16CPU" */ = { 331 | isa = XCConfigurationList; 332 | buildConfigurations = ( 333 | 523E54B41E90431E007D2654 /* Debug */, 334 | 523E54B51E90431E007D2654 /* Release */, 335 | ); 336 | defaultConfigurationIsVisible = 0; 337 | defaultConfigurationName = Release; 338 | }; 339 | 523E54B61E90431E007D2654 /* Build configuration list for PBXNativeTarget "Intel16CPU" */ = { 340 | isa = XCConfigurationList; 341 | buildConfigurations = ( 342 | 523E54B71E90431E007D2654 /* Debug */, 343 | 523E54B81E90431E007D2654 /* Release */, 344 | ); 345 | defaultConfigurationIsVisible = 0; 346 | defaultConfigurationName = Release; 347 | }; 348 | /* End XCConfigurationList section */ 349 | }; 350 | rootObject = 523E54A81E90431E007D2654 /* Project object */; 351 | } 352 | -------------------------------------------------------------------------------- /Intel16CPU/Intel16CPU/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | NSHumanReadableCopyright 22 | Copyright © 2017 bjfn. All rights reserved. 23 | NSPrincipalClass 24 | Intel16CPU 25 | 26 | 27 | -------------------------------------------------------------------------------- /Intel16CPU/Intel16CPU/Intel16CPU.h: -------------------------------------------------------------------------------- 1 | // 2 | // Intel16CPU.h 3 | // Intel16CPU 4 | // 5 | // Created by john on 01.04.17. 6 | // Copyright © 2017 bjfn. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #include 12 | 13 | typedef NS_ENUM(NSUInteger, GRegs) { 14 | AH=0, AL, BH, BL, CH, CL, DH, DL, AX, BX, CX, DX, BP, SP, SI, DI, 15 | EAX, EBX, ECX, EDX, EBP, ESP, ESI, EDI 16 | }; 17 | 18 | typedef NS_ENUM(NSUInteger, SRegs) { 19 | IP=0, EIP 20 | }; 21 | 22 | #define UNDEFINED_STATE ((int64_t)-1) 23 | 24 | @interface Intel16CPU : NSObject 25 | 26 | - (NSObject *)hopperServices; 27 | - (void)setFile:(NSObject*)file; 28 | 29 | - (NSUInteger)capstoneToRegIndex:(x86_reg)reg; 30 | - (RegClass)capstoneToRegClass:(x86_reg)reg; 31 | - (void)clearState; 32 | - (void)updateState:(DisasmStruct*)disasm; 33 | - (void)setCapstoneReg:(x86_reg)reg value:(int64_t)value; 34 | - (int64_t)getCapstoneReg:(x86_reg)reg; 35 | - (void)setReg:(NSUInteger)reg ofClass:(RegClass)rclass value:(int64_t)value; 36 | - (int64_t)getReg:(NSUInteger)reg ofClass:(RegClass)rclass; 37 | - (uint)getCS; 38 | - (uint)getIP; 39 | - (uint64_t)dataSeg; 40 | @end 41 | -------------------------------------------------------------------------------- /Intel16CPU/Intel16CPU/Intel16CPU.mm: -------------------------------------------------------------------------------- 1 | // 2 | // Intel16CPU.m 3 | // Intel16CPU 4 | // 5 | // Created by john on 01.04.17. 6 | // Copyright © 2017 bjfn. All rights reserved. 7 | // 8 | 9 | #import "Intel16CPU.h" 10 | #import "Intel16Ctx.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "../../DOSComLoader/DOSComLoader/ComLoader.h" 17 | 18 | using namespace std; 19 | 20 | #define OP_CAN_DEFINE 1 21 | #define OP_DEF_SELF 2 22 | #define OP_UNARY 4 23 | 24 | 25 | struct RegInfo{ 26 | x86_reg capstone; 27 | NSUInteger rid; 28 | RegClass rclass; 29 | int64_t *statePtr; 30 | int size; 31 | NSString* name; 32 | }; 33 | 34 | static struct CpuState{ 35 | int64_t EAX, EBX, ECX, EDX, EBP, ESP, ESI, EDI, EIP; 36 | int64_t ES, DS, FS, GS, CS, SS; 37 | int64_t EFLAGS; 38 | vector stack; 39 | } _state; 40 | 41 | struct OpInfo{ 42 | x86_insn insn; 43 | int flags; 44 | function proc; 45 | }; 46 | 47 | static RegInfo regs[] = { 48 | {X86_REG_EFLAGS, 0, RegClass_CPUState, &_state.EFLAGS, 4, @"eflags"}, 49 | {X86_REG_AL, AL, RegClass_GeneralPurposeRegister, &_state.EAX, 1, @"al"}, 50 | {X86_REG_AH, AH, RegClass_GeneralPurposeRegister, &_state.EAX, 0x101, @"ah"}, 51 | {X86_REG_AX, AX, RegClass_GeneralPurposeRegister, &_state.EAX, 2, @"ax"}, 52 | {X86_REG_EAX, EAX, RegClass_GeneralPurposeRegister, &_state.EAX, 4, @"eax"}, 53 | {X86_REG_BL, BL, RegClass_GeneralPurposeRegister, &_state.EBX, 1, @"bl"}, 54 | {X86_REG_BH, BH, RegClass_GeneralPurposeRegister, &_state.EBX, 0x101, @"bh"}, 55 | {X86_REG_BX, BX, RegClass_GeneralPurposeRegister, &_state.EBX, 2, @"bx"}, 56 | {X86_REG_EBX, EBX, RegClass_GeneralPurposeRegister, &_state.EBX, 4, @"ebx"}, 57 | {X86_REG_CL, CL, RegClass_GeneralPurposeRegister, &_state.ECX, 1, @"cl"}, 58 | {X86_REG_CH, CH, RegClass_GeneralPurposeRegister, &_state.ECX, 0x101, @"ch"}, 59 | {X86_REG_CX, CX, RegClass_GeneralPurposeRegister, &_state.ECX, 2, @"cx"}, 60 | {X86_REG_ECX, ECX, RegClass_GeneralPurposeRegister, &_state.ECX, 4, @"ecx"}, 61 | {X86_REG_DL, DL, RegClass_GeneralPurposeRegister, &_state.EDX, 1, @"dl"}, 62 | {X86_REG_DH, DH, RegClass_GeneralPurposeRegister, &_state.EDX, 0x101, @"dh"}, 63 | {X86_REG_DX, DX, RegClass_GeneralPurposeRegister, &_state.EDX, 2, @"dx"}, 64 | {X86_REG_EDX, EDX, RegClass_GeneralPurposeRegister, &_state.EDX, 4, @"edx"}, 65 | {X86_REG_BP, BP, RegClass_GeneralPurposeRegister, &_state.EBP, 2, @"bp"}, 66 | {X86_REG_EBP, EBP, RegClass_GeneralPurposeRegister, &_state.EBP, 4, @"ebp"}, 67 | {X86_REG_SP, SP, RegClass_GeneralPurposeRegister, &_state.ESP, 2, @"sp"}, 68 | {X86_REG_ESP, ESP, RegClass_GeneralPurposeRegister, &_state.ESP, 4, @"esp"}, 69 | {X86_REG_SI, SI, RegClass_GeneralPurposeRegister, &_state.ESI, 2, @"si"}, 70 | {X86_REG_ESI, ESI, RegClass_GeneralPurposeRegister, &_state.ESI, 4, @"esi"}, 71 | {X86_REG_DI, DI, RegClass_GeneralPurposeRegister, &_state.EDI, 2, @"di"}, 72 | {X86_REG_EDI, EDI, RegClass_GeneralPurposeRegister, &_state.EDI, 4, @"edi"}, 73 | {X86_REG_IP, IP, RegClass_X86_Special, &_state.EIP, 2, @"ip"}, 74 | {X86_REG_EIP, EIP, RegClass_X86_Special, &_state.EIP, 4, @"eip"}, 75 | {X86_REG_CS, DISASM_CS_Reg, RegClass_X86_SEG, &_state.CS, 2, @"cs"}, 76 | {X86_REG_DS, DISASM_DS_Reg, RegClass_X86_SEG, &_state.DS, 2, @"ds"}, 77 | {X86_REG_ES, DISASM_ES_Reg, RegClass_X86_SEG, &_state.ES, 2, @"es"}, 78 | {X86_REG_SS, DISASM_SS_Reg, RegClass_X86_SEG, &_state.SS, 2, @"ss"}, 79 | {X86_REG_FS, DISASM_FS_Reg, RegClass_X86_SEG, &_state.FS, 2, @"fs"}, 80 | {X86_REG_GS, DISASM_GS_Reg, RegClass_X86_SEG, &_state.GS, 2, @"gs"}, 81 | {X86_REG_INVALID, 0, RegClass_X86_SEG, NULL, 2, @"invalid"}, 82 | }; 83 | 84 | static OpInfo ops[] = { 85 | {X86_INS_MOV, OP_CAN_DEFINE, [](uint64_t r,uint64_t v) {return v;}}, 86 | {X86_INS_XOR, OP_CAN_DEFINE | OP_DEF_SELF, [](uint64_t r,uint64_t v) {return r ^ v;}}, 87 | {X86_INS_SUB, OP_CAN_DEFINE | OP_DEF_SELF, [](uint64_t r,uint64_t v) {return r - v;}}, 88 | {X86_INS_ADD, 0, [](uint64_t r,uint64_t v) {return r + v;}}, 89 | {X86_INS_AND, 0, [](uint64_t r,uint64_t v) {return r & v;}}, 90 | {X86_INS_OR, 0, [](uint64_t r,uint64_t v) {return r | v;}}, 91 | {X86_INS_INC, OP_UNARY, [](uint64_t r,uint64_t v) {return r+1;}}, 92 | {X86_INS_DEC, OP_UNARY, [](uint64_t r,uint64_t v) {return r-1;}}, 93 | {X86_INS_NOT, OP_UNARY, [](uint64_t r,uint64_t v) {return ~r;}}, 94 | {X86_INS_PUSH, OP_UNARY | OP_CAN_DEFINE, [](uint64_t r,uint64_t v) {_state.stack.push_back(r); return r;}}, 95 | {X86_INS_POP, OP_UNARY | OP_CAN_DEFINE, [](uint64_t r,uint64_t v) { 96 | if (_state.stack.size()==0) 97 | return (uint64_t)UNDEFINED_STATE; 98 | r=_state.stack.back(); 99 | _state.stack.pop_back(); 100 | return r; 101 | }}, 102 | {X86_INS_INVALID, 0, nullptr}, 103 | }; 104 | 105 | 106 | @implementation Intel16CPU { 107 | NSObject *_services; 108 | NSObject *_file; 109 | map capstoneRegs; 110 | map> localRegs; 111 | BOOL isComFile; 112 | map procs; 113 | uint64_t dataSeg; 114 | } 115 | 116 | - (instancetype)initWithHopperServices:(NSObject *)services { 117 | if (self = [super init]) { 118 | _services = services; 119 | isComFile = -1; 120 | for (RegInfo& it: regs){ 121 | capstoneRegs[it.capstone] = ⁢ 122 | localRegs[it.rclass][it.rid] = ⁢ 123 | if (it.capstone==X86_REG_INVALID){ 124 | break; 125 | } 126 | } 127 | for (OpInfo& it: ops){ 128 | if (it.insn == X86_INS_INVALID){ 129 | break; 130 | } 131 | procs[it.insn] = ⁢ 132 | } 133 | [self clearState]; 134 | } 135 | return self; 136 | } 137 | 138 | - (void)setFile:(NSObject*)file{ 139 | _file = file; 140 | isComFile = [[[_file firstSegment] segmentName] isEqualToString: COM_SEGMENT]; 141 | [self setCapstoneReg:X86_REG_FS value:UNDEFINED_STATE]; 142 | [self setCapstoneReg:X86_REG_GS value:UNDEFINED_STATE]; 143 | [self setCapstoneReg:X86_REG_SS value:UNDEFINED_STATE]; 144 | [self setCapstoneReg:X86_REG_CS value:UNDEFINED_STATE]; 145 | dataSeg = UNDEFINED_STATE; 146 | NSObject *seg = [_file firstSegment]; 147 | for (int i=0;i<[seg sectionCount];i++){ 148 | NSObject * sec = [[seg sections] objectAtIndex:i]; 149 | if (sec.pureDataSection){ 150 | dataSeg = [sec startAddress] >> 4; 151 | break; 152 | } 153 | } 154 | [self setCapstoneReg:X86_REG_DS value:dataSeg]; 155 | [self setCapstoneReg:X86_REG_ES value:dataSeg]; 156 | } 157 | 158 | - (NSObject *)hopperServices { 159 | return _services; 160 | } 161 | 162 | - (NSObject *)buildCPUContextForFile:(NSObject *)file { 163 | return [[Intel16Ctx alloc] initWithCPU:self andFile:file]; 164 | } 165 | 166 | - (nonnull NSObject *)pluginUUID { 167 | return [_services UUIDWithString:@"9f8d07d0-b9d4-4a96-8862-392ed8028cd6"]; 168 | } 169 | 170 | - (HopperPluginType)pluginType { 171 | return Plugin_CPU; 172 | } 173 | 174 | - (NSString *)pluginName { 175 | return @"Intel16"; 176 | } 177 | 178 | - (NSString *)pluginDescription { 179 | return @"Intel x86 16-bit CPU support"; 180 | } 181 | 182 | - (NSString *)pluginAuthor { 183 | return @"bjohnfn@gmail.com"; 184 | } 185 | 186 | - (NSString *)pluginCopyright { 187 | return @"©2017 - bjohnfn@gmail.com"; 188 | } 189 | 190 | - (NSArray *)cpuFamilies { 191 | return @[@"intel16"]; 192 | } 193 | 194 | - (NSString *)pluginVersion { 195 | return @"0.0.1"; 196 | } 197 | 198 | - (nonnull NSString *)commandLineIdentifier { 199 | return @"IA16"; 200 | } 201 | 202 | 203 | + (int)sdkVersion { 204 | return HOPPER_CURRENT_SDK_VERSION; 205 | } 206 | 207 | 208 | - (NSArray *)cpuSubFamiliesForFamily:(NSString *)family { 209 | if ([family isEqualToString:@"intel16"]) return @[@"8086"]; 210 | return nil; 211 | } 212 | 213 | - (int)addressSpaceWidthInBitsForCPUFamily:(NSString *)family andSubFamily:(NSString *)subFamily { 214 | if ([family isEqualToString:@"intel16"] && [subFamily isEqualToString:@"8086"]) return 16; 215 | return 0; 216 | } 217 | 218 | - (CPUEndianess)endianess { 219 | return CPUEndianess_Little; 220 | } 221 | 222 | - (NSUInteger)cpuModeCount { 223 | return 2; 224 | } 225 | 226 | - (Class)cpuContextClass { 227 | return [Intel16Ctx class]; 228 | } 229 | 230 | - (NSArray *)cpuModeNames { 231 | return @[@"real", @"protected"]; 232 | } 233 | 234 | - (NSUInteger)syntaxVariantCount { 235 | return 4; 236 | } 237 | 238 | - (NSArray *)syntaxVariantNames { 239 | return @[@"intel", @"AT&T", @"intel s:o", @"AT&T s:o"]; 240 | } 241 | 242 | - (NSString *)framePointerRegisterNameForFile:(NSObject *)file { 243 | return nil; 244 | } 245 | 246 | - (NSUInteger)registerClassCount { 247 | return RegClass_X86_SEG+1; 248 | } 249 | 250 | - (NSUInteger)registerCountForClass:(RegClass)reg_class { 251 | switch (reg_class) { 252 | case RegClass_CPUState: return 1; 253 | case RegClass_GeneralPurposeRegister: return EDI+1; 254 | case RegClass_X86_SEG: return DISASM_SS_Reg+1; 255 | case RegClass_X86_Special: return EIP+1; 256 | default: break; 257 | } 258 | return 0; 259 | } 260 | 261 | - (BOOL)registerIndexIsStackPointer:(NSUInteger)reg ofClass:(RegClass)reg_class { 262 | return reg_class == RegClass_GeneralPurposeRegister && (reg == SP || reg == ESP); 263 | } 264 | 265 | - (BOOL)registerIndexIsFrameBasePointer:(NSUInteger)reg ofClass:(RegClass)reg_class { 266 | return reg_class == RegClass_GeneralPurposeRegister && (reg == BP || reg == EBP); 267 | } 268 | 269 | - (BOOL)registerIndexIsProgramCounter:(NSUInteger)reg { 270 | return NO; 271 | } 272 | 273 | - (BOOL)registerHasSideEffectForIndex:(NSUInteger)reg andClass:(RegClass)reg_class { 274 | return NO; 275 | } 276 | 277 | - (NSString *)registerIndexToString:(NSUInteger)reg ofClass:(RegClass)reg_class withBitSize:(NSUInteger)size position:(DisasmPosition)position andSyntaxIndex:(NSUInteger)syntaxIndex { 278 | RegInfo* info = localRegs[reg_class][reg]; 279 | return info ? info->name : nil; 280 | } 281 | 282 | - (NSString *)cpuRegisterStateMaskToString:(uint32_t)cpuState { 283 | return @""; 284 | } 285 | 286 | - (NSUInteger)translateOperandIndex:(NSUInteger)index operandCount:(NSUInteger)count accordingToSyntax:(uint8_t)syntaxIndex { 287 | return index; 288 | } 289 | 290 | - (NSData *)nopWithSize:(NSUInteger)size andMode:(NSUInteger)cpuMode forFile:(NSObject *)file { 291 | NSMutableData *nopArray = [[NSMutableData alloc] initWithCapacity:size]; 292 | [nopArray setLength:size]; 293 | uint16_t *ptr = (uint16_t *)[nopArray mutableBytes]; 294 | for (NSUInteger i=0; i *)file cpuMode:(uint8_t)cpuMode { 309 | return [self framePointerRegisterNameForFile: file]; 310 | } 311 | 312 | 313 | - (int)integerWidthInBitsForCPUFamily:(nullable NSString *)family andSubFamily:(nullable NSString *)subFamily { 314 | return 32; 315 | } 316 | 317 | 318 | - (BOOL)registerIndexIsFrameBasePointer:(NSUInteger)reg ofClass:(RegClass)reg_class cpuMode:(uint8_t)cpuMode file:(nonnull NSObject *)file { 319 | return [self registerIndexIsFrameBasePointer: reg ofClass: reg_class]; 320 | } 321 | 322 | 323 | - (BOOL)registerIndexIsProgramCounter:(NSUInteger)reg cpuMode:(uint8_t)cpuMode file:(nonnull NSObject *)file { 324 | return [self registerIndexIsProgramCounter: reg]; 325 | } 326 | 327 | 328 | - (BOOL)registerIndexIsStackPointer:(NSUInteger)reg ofClass:(RegClass)reg_class cpuMode:(uint8_t)cpuMode file:(nonnull NSObject *)file { 329 | return [self registerIndexIsStackPointer: reg ofClass: reg_class]; 330 | } 331 | 332 | 333 | - (NSUInteger)capstoneToRegIndex:(x86_reg)reg { 334 | RegInfo* info = capstoneRegs[reg]; 335 | return info ? info->rid : 0; 336 | } 337 | 338 | - (RegClass)capstoneToRegClass:(x86_reg)reg { 339 | RegInfo* info = capstoneRegs[reg]; 340 | return info ? info->rclass : RegClass_CPUState; 341 | } 342 | 343 | - (void)clearState { 344 | //undefine GP regs 345 | memset(&_state, 0xFF, 8*sizeof(int64_t)); 346 | _state.stack.clear(); 347 | [self setCapstoneReg:X86_REG_DS value:dataSeg]; 348 | [self setCapstoneReg:X86_REG_ES value:dataSeg]; 349 | } 350 | 351 | - (void)updateCSIP:(DisasmStruct*)disasm { 352 | Address va = disasm->virtualAddr; 353 | Address start=0; 354 | if (!isComFile){ 355 | start=[_file sectionForVirtualAddress:va].startAddress; 356 | } 357 | uint64_t seg = start >> 4; 358 | [self setCapstoneReg:X86_REG_CS value:seg]; 359 | [self setCapstoneReg:X86_REG_EIP value:va-(seg<<4)]; 360 | } 361 | 362 | - (void)updateState:(DisasmStruct*)disasm{ 363 | [self updateCSIP:disasm]; 364 | x86_insn opId = (x86_insn)disasm->instruction.userData; 365 | if (!procs.count(opId)){ 366 | return; 367 | } 368 | DisasmOperand* dop=&disasm->operand[0]; 369 | DisasmOperand* sop=&disasm->operand[1]; 370 | if (sop->type == DISASM_OPERAND_NO_OPERAND){ 371 | //one operand 372 | sop = dop; 373 | } 374 | if (disasm->syntaxIndex & 1){ 375 | //AT & T switch dest/source operands 376 | swap(dop, sop); 377 | } 378 | if (!(dop->type & DISASM_OPERAND_REGISTER_TYPE)){ 379 | //not register dest 380 | return; 381 | } 382 | OpInfo* op = procs[opId]; 383 | x86_reg dreg =(x86_reg)dop->userData[0]; 384 | uint64_t val = [self getCapstoneReg:dreg]; 385 | if (val == UNDEFINED_STATE){ 386 | if (!(op->flags & OP_CAN_DEFINE)){ 387 | return; 388 | } 389 | if (op->flags & OP_DEF_SELF && dop->type==sop->type){ 390 | [self setCapstoneReg:dreg value:0]; 391 | return; 392 | } 393 | } 394 | if (op->flags & OP_UNARY){ 395 | [self setCapstoneReg:dreg value:op->proc(val, 0)]; 396 | return; 397 | } 398 | uint64_t v2=0; 399 | if (sop->type & DISASM_OPERAND_CONSTANT_TYPE){ 400 | v2 = sop->immediateValue; 401 | }else if (sop->type & DISASM_OPERAND_REGISTER_TYPE){ 402 | //reg 403 | x86_reg reg = (x86_reg)sop->userData[0]; 404 | v2 = [self getCapstoneReg:reg]; 405 | }else{ 406 | //undefine 407 | v2 = UNDEFINED_STATE; 408 | } 409 | if (v2 == UNDEFINED_STATE){ 410 | [self setCapstoneReg:dreg value:UNDEFINED_STATE]; 411 | }else{ 412 | [self setCapstoneReg:dreg value:op->proc((uint32_t)val, (uint32_t)v2)]; 413 | } 414 | } 415 | 416 | - (void)setRegInfo:(RegInfo*)info value:(int64_t)value { 417 | if(!info || !info->statePtr){ 418 | NSLog(@"Reg not found."); 419 | return; 420 | } 421 | if (value == UNDEFINED_STATE){ 422 | *info->statePtr = value; 423 | return; 424 | } 425 | int ofs = (info->size >> 8) & 0xFF; 426 | memcpy(((uint8_t*)info->statePtr)+ofs, &value, info->size & 0xFF); 427 | } 428 | 429 | - (void)setCapstoneReg:(x86_reg)reg value:(int64_t)value{ 430 | [self setRegInfo:capstoneRegs[reg] value:value]; 431 | } 432 | 433 | 434 | - (void)setReg:(NSUInteger)reg ofClass:(RegClass)rclass value:(int64_t)value{ 435 | [self setRegInfo:localRegs[rclass][reg] value:value]; 436 | } 437 | 438 | - (int64_t)getRegInfoValue:(RegInfo*)info { 439 | if(!info || !info->statePtr || *info->statePtr==UNDEFINED_STATE){ 440 | return UNDEFINED_STATE; 441 | } 442 | int ofs = (info->size >> 8) & 0xFF; 443 | int64_t res = 0; 444 | memcpy(&res, ((uint8_t*)info->statePtr)+ofs, info->size & 0xFF); 445 | return res; 446 | } 447 | 448 | - (int64_t)getCapstoneReg:(x86_reg)reg { 449 | return [self getRegInfoValue:capstoneRegs[reg]]; 450 | } 451 | 452 | 453 | - (int64_t)getReg:(NSUInteger)reg ofClass:(RegClass)rclass{ 454 | return [self getRegInfoValue:localRegs[rclass][reg]]; 455 | } 456 | 457 | - (uint)getCS{ 458 | return (uint)[self getCapstoneReg:X86_REG_CS]; 459 | } 460 | 461 | - (uint)getIP{ 462 | return (uint)[self getCapstoneReg:X86_REG_EIP]; 463 | } 464 | 465 | - (uint64_t)dataSeg{ 466 | return dataSeg; 467 | } 468 | 469 | 470 | @end 471 | -------------------------------------------------------------------------------- /Intel16CPU/Intel16CPU/Intel16Ctx.h: -------------------------------------------------------------------------------- 1 | // 2 | // Intel16Ctx.h 3 | // Intel16CPU 4 | // 5 | // Created by john on 01.04.17. 6 | // Copyright © 2017 bjfn. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class Intel16CPU; 13 | 14 | @interface Intel16Ctx : NSObject 15 | 16 | - (instancetype)initWithCPU:(Intel16CPU *)cpu andFile:(NSObject *)file; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Intel16CPU/Intel16CPU/Intel16Ctx.m: -------------------------------------------------------------------------------- 1 | // 2 | // Intel16Ctx.m 3 | // Intel16CPU 4 | // 5 | // Created by john on 01.04.17. 6 | // Copyright © 2017 bjfn. All rights reserved. 7 | // 8 | 9 | #import "Intel16Ctx.h" 10 | #import "Intel16CPU.h" 11 | #import 12 | #import 13 | #import 14 | #import "OpComment.h" 15 | 16 | #include 17 | #include 18 | 19 | #define FORMAT(fmt) if (format == Format_Default) format = fmt 20 | 21 | @implementation Intel16Ctx { 22 | Intel16CPU *_cpu; 23 | NSObject *_file; 24 | csh _handle; 25 | NSArray* intelPtrs; 26 | uint64_t maxAddress; 27 | } 28 | 29 | - (instancetype)initWithCPU:(Intel16CPU *)cpu andFile:(NSObject *)file { 30 | if (self = [super init]) { 31 | _cpu = cpu; 32 | _file = file; 33 | if (cs_open(CS_ARCH_X86, CS_MODE_16, &_handle) != CS_ERR_OK) { 34 | return nil; 35 | } 36 | cs_option(_handle, CS_OPT_DETAIL, CS_OPT_ON); 37 | if (file.userRequestedSyntaxIndex & 1){ 38 | cs_option(_handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); 39 | }else{ 40 | cs_option(_handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL); 41 | } 42 | intelPtrs = @[@"byte ptr ", @"word ptr ", @"dword ptr "]; 43 | [_cpu setFile:file]; 44 | maxAddress = [[file firstSegment] endAddress]; 45 | } 46 | return self; 47 | } 48 | 49 | - (void)dealloc { 50 | cs_close(&_handle); 51 | } 52 | 53 | - (NSObject *)cpuDefinition { 54 | return _cpu; 55 | } 56 | 57 | - (void)initDisasmStructure:(DisasmStruct*)disasm withSyntaxIndex:(NSUInteger)syntaxIndex { 58 | bzero(disasm, sizeof(DisasmStruct)); 59 | disasm->syntaxIndex = _file.userRequestedSyntaxIndex; 60 | } 61 | 62 | // Analysis 63 | 64 | - (Address)adjustCodeAddress:(Address)address { 65 | return address; 66 | } 67 | 68 | - (uint8_t)cpuModeFromAddress:(Address)address { 69 | return 0; 70 | } 71 | 72 | - (BOOL)addressForcesACPUMode:(Address)address { 73 | return NO; 74 | } 75 | 76 | - (Address)nextAddressToTryIfInstructionFailedToDecodeAt:(Address)address forCPUMode:(uint8_t)mode { 77 | return address+1; 78 | } 79 | 80 | - (int)isNopAt:(Address)address { 81 | uint8_t byte = [_file readUInt8AtVirtualAddress:address]; 82 | return byte==0x90; 83 | } 84 | 85 | - (BOOL)hasProcedurePrologAt:(Address)address { 86 | uint32_t data = [_file readUInt32AtVirtualAddress:address]; 87 | return (data & 0x00FFFFFF) == 0xEC8B55; 88 | } 89 | 90 | - (NSUInteger)detectedPaddingLengthAt:(Address)address { 91 | return 0; 92 | } 93 | 94 | - (void)analysisBeginsAt:(Address)entryPoint { 95 | 96 | } 97 | 98 | - (void)analysisEnded { 99 | 100 | } 101 | 102 | - (void)procedureAnalysisBeginsForProcedure:(NSObject *)procedure atEntryPoint:(Address)entryPoint { 103 | [_cpu clearState]; 104 | } 105 | 106 | - (void)procedureAnalysisOfPrologForProcedure:(NSObject *)procedure atEntryPoint:(Address)entryPoint { 107 | 108 | } 109 | 110 | - (void)procedureAnalysisOfEpilogForProcedure:(NSObject *)procedure atEntryPoint:(Address)entryPoint { 111 | 112 | } 113 | 114 | - (void)procedureAnalysisEndedForProcedure:(NSObject *)procedure atEntryPoint:(Address)entryPoint { 115 | [_cpu clearState]; 116 | } 117 | 118 | - (void)procedureAnalysisContinuesOnBasicBlock:(NSObject *)basicBlock { 119 | 120 | } 121 | 122 | - (Address)getThunkDestinationForInstructionAt:(Address)address { 123 | return BAD_ADDRESS; 124 | } 125 | 126 | - (void)resetDisassembler { 127 | 128 | } 129 | 130 | - (uint8_t)estimateCPUModeAtVirtualAddress:(Address)address { 131 | return 0; 132 | } 133 | 134 | 135 | - (int)disassembleSingleInstruction:(DisasmStruct *)disasm usingProcessorMode:(NSUInteger)mode { 136 | if (disasm->bytes == NULL) return DISASM_UNKNOWN_OPCODE; 137 | 138 | cs_insn *insn; 139 | size_t count = cs_disasm(_handle, disasm->bytes, 16, disasm->virtualAddr, 1, &insn); 140 | if (count == 0) return DISASM_UNKNOWN_OPCODE; 141 | 142 | disasm->instruction.branchType = DISASM_BRANCH_NONE; 143 | disasm->instruction.addressValue = 0; 144 | disasm->instruction.userData = insn->id; 145 | disasm->instruction.pcRegisterValue = disasm->virtualAddr + insn->size; 146 | 147 | int op_index; 148 | for (op_index=0; op_indexdetail->x86.op_count; op_index++) { 149 | cs_x86_op *op = insn->detail->x86.operands + op_index; 150 | DisasmOperand *hop_op = disasm->operand + op_index; 151 | 152 | switch (op->type) { 153 | case X86_OP_IMM: 154 | hop_op->type = DISASM_OPERAND_CONSTANT_TYPE; 155 | hop_op->immediateValue = op->imm; 156 | break; 157 | 158 | case X86_OP_REG: 159 | hop_op->userData[0] = op->reg; 160 | hop_op->type = DISASM_OPERAND_REGISTER_TYPE; 161 | hop_op->type |= DISASM_BUILD_REGISTER_CLS_MASK([_cpu capstoneToRegClass:op->reg]); 162 | hop_op->type |= DISASM_BUILD_REGISTER_INDEX_MASK([_cpu capstoneToRegIndex:op->reg]); 163 | break; 164 | 165 | 166 | case X86_OP_MEM: { 167 | hop_op->type = DISASM_OPERAND_MEMORY_TYPE; 168 | hop_op->memory.displacement = (int16_t) op->mem.disp; 169 | BOOL dispOnly=YES; 170 | DisasmSegmentReg seg = DISASM_DS_Reg; 171 | if (op->mem.segment != X86_REG_INVALID){ 172 | hop_op->segmentReg = (DisasmSegmentReg)[_cpu capstoneToRegIndex:op->mem.segment]; 173 | seg = hop_op->segmentReg; 174 | } 175 | if (op->mem.base!=X86_REG_INVALID){ 176 | hop_op->type |= DISASM_BUILD_REGISTER_CLS_MASK(RegClass_GeneralPurposeRegister); 177 | uint64_t mask = DISASM_BUILD_REGISTER_INDEX_MASK([_cpu capstoneToRegIndex:op->mem.base]); 178 | hop_op->type |= mask; 179 | hop_op->memory.baseRegistersMask = mask; 180 | dispOnly = NO; 181 | } 182 | if (op->mem.index!=X86_REG_INVALID){ 183 | hop_op->type |= DISASM_BUILD_REGISTER_CLS_MASK(RegClass_GeneralPurposeRegister); 184 | uint64_t mask = DISASM_BUILD_REGISTER_INDEX_MASK([_cpu capstoneToRegIndex:op->mem.index]); 185 | hop_op->type |= mask; 186 | hop_op->memory.indexRegistersMask = mask; 187 | hop_op->memory.scale = op->mem.scale; 188 | dispOnly = NO; 189 | } 190 | 191 | if (dispOnly && op->mem.disp){ 192 | uint64_t a = [_cpu getReg:seg ofClass:RegClass_X86_SEG]; 193 | if (a == UNDEFINED_STATE){ 194 | a = [_cpu dataSeg]; 195 | } 196 | if (a!=UNDEFINED_STATE){ 197 | disasm->instruction.addressValue = (a<<4) + hop_op->memory.displacement; 198 | } 199 | } 200 | 201 | hop_op->size = op->size * 8; 202 | break; 203 | } 204 | 205 | default: 206 | hop_op->type = DISASM_OPERAND_OTHER; 207 | break; 208 | } 209 | 210 | } 211 | for ( ; op_index < DISASM_MAX_OPERANDS; op_index++) { 212 | disasm->operand[op_index].type = DISASM_OPERAND_NO_OPERAND; 213 | } 214 | strcpy(disasm->instruction.mnemonic, insn->mnemonic); 215 | 216 | // In this early version, only branch instructions are analyzed in order to correctly 217 | // construct basic blocks of procedures. 218 | // 219 | // This is the strict minimum! 220 | // 221 | // You should also fill the "operand" description for every other instruction to take 222 | // advantage of the various analysis of Hopper. 223 | bool loop = (insn->id == X86_INS_LOOP || insn->id == X86_INS_LOOPE || insn->id == X86_INS_LOOPNE); 224 | 225 | if (loop || cs_insn_group(_handle, insn, X86_GRP_JUMP) || cs_insn_group(_handle, insn, X86_GRP_CALL)) { 226 | disasm->instruction.addressValue = 0; 227 | disasm->operand[0].type |= DISASM_OPERAND_ABSOLUTE; 228 | do{ 229 | if (insn->detail->x86.op_count <1) 230 | break; 231 | if (insn->detail->x86.operands[0].type!=X86_OP_IMM) 232 | break; 233 | disasm->operand[0].isBranchDestination = 1; 234 | uint8_t op = disasm->bytes[0]; 235 | int16_t *op16 = (int16_t*)(disasm->bytes+1); 236 | if (op == 0x9A || op == 0xEA){ 237 | //ptr16:16 238 | disasm->instruction.addressValue = op16[0] + (op16[1]<<4); 239 | disasm->operand[0].size = 32; 240 | disasm->operand[1].type = DISASM_OPERAND_NO_OPERAND; 241 | break; 242 | } 243 | if (op==0xE9 || op == 0xE8){ 244 | //rel16 245 | disasm->instruction.addressValue = disasm->virtualAddr + insn->size + op16[0]; 246 | break; 247 | } 248 | //rel 8 249 | int8_t *op8 = (int8_t*)disasm->bytes+1; 250 | disasm->instruction.addressValue = disasm->virtualAddr + insn->size + op8[0]; 251 | }while(0); 252 | if (disasm->instruction.addressValue){ 253 | disasm->operand[0].immediateValue = disasm->instruction.addressValue; 254 | } 255 | 256 | if(cs_insn_group(_handle, insn, X86_GRP_CALL)){ 257 | disasm->instruction.branchType = DISASM_BRANCH_CALL; 258 | } 259 | 260 | switch(insn->id) { 261 | case X86_INS_JGE: 262 | case X86_INS_JAE: 263 | disasm->instruction.branchType = DISASM_BRANCH_JGE; 264 | break; 265 | case X86_INS_JA: 266 | disasm->instruction.branchType = DISASM_BRANCH_JA; 267 | break; 268 | case X86_INS_JLE: 269 | case X86_INS_JBE: 270 | disasm->instruction.branchType = DISASM_BRANCH_JLE; 271 | break; 272 | case X86_INS_JB: 273 | disasm->instruction.branchType = DISASM_BRANCH_JB; 274 | break; 275 | case X86_INS_JCXZ: 276 | disasm->instruction.branchType = DISASM_BRANCH_JCXZ; 277 | break; 278 | case X86_INS_JECXZ: 279 | case X86_INS_LOOP: 280 | case X86_INS_LOOPE: 281 | case X86_INS_LOOPNE: 282 | disasm->instruction.branchType = DISASM_BRANCH_JECXZ; 283 | break; 284 | case X86_INS_JE: 285 | disasm->instruction.branchType = DISASM_BRANCH_JE; 286 | break; 287 | case X86_INS_JG: 288 | disasm->instruction.branchType = DISASM_BRANCH_JG; 289 | break; 290 | case X86_INS_JL: 291 | disasm->instruction.branchType = DISASM_BRANCH_JL; 292 | break; 293 | case X86_INS_JMP: 294 | case X86_INS_LJMP: 295 | disasm->instruction.branchType = DISASM_BRANCH_JMP; 296 | break; 297 | case X86_INS_JNE: 298 | disasm->instruction.branchType = DISASM_BRANCH_JNE; 299 | break; 300 | case X86_INS_JNO: 301 | disasm->instruction.branchType = DISASM_BRANCH_JNO; 302 | break; 303 | case X86_INS_JNP: 304 | disasm->instruction.branchType = DISASM_BRANCH_JNP; 305 | break; 306 | case X86_INS_JNS: 307 | disasm->instruction.branchType = DISASM_BRANCH_JNS; 308 | break; 309 | case X86_INS_JO: 310 | disasm->instruction.branchType = DISASM_BRANCH_JO; 311 | break; 312 | case X86_INS_JP: 313 | disasm->instruction.branchType = DISASM_BRANCH_JP; 314 | break; 315 | case X86_INS_JRCXZ: 316 | disasm->instruction.branchType = DISASM_BRANCH_JRCXZ; 317 | break; 318 | case X86_INS_JS: 319 | disasm->instruction.branchType = DISASM_BRANCH_JS; 320 | break; 321 | } 322 | } 323 | 324 | if (cs_insn_group(_handle, insn, X86_GRP_RET) || cs_insn_group(_handle, insn, X86_GRP_IRET)) { 325 | disasm->instruction.branchType = DISASM_BRANCH_RET; 326 | } 327 | 328 | int len = (int) insn->size; 329 | cs_free(insn, count); 330 | 331 | [_cpu updateState:disasm]; 332 | 333 | return len; 334 | } 335 | 336 | - (BOOL)instructionHaltsExecutionFlow:(DisasmStruct *)disasm { 337 | return NO; 338 | } 339 | 340 | - (void)performBranchesAnalysis:(DisasmStruct *)disasm computingNextAddress:(Address *)next andBranches:(NSMutableArray *)branches forProcedure:(NSObject *)procedure basicBlock:(NSObject *)basicBlock ofSegment:(NSObject *)segment calledAddresses:(NSMutableArray *)calledAddresses callsites:(NSMutableArray *)callSitesAddresses { 341 | 342 | } 343 | 344 | - (void)performInstructionSpecificAnalysis:(DisasmStruct *)disasm forProcedure:(NSObject *)procedure inSegment:(NSObject *)segment { 345 | NSString* comment = [OpComment commentForOpcode:disasm CPU:_cpu]; 346 | if (comment){ 347 | [_file setComment:comment atVirtualAddress:disasm->virtualAddr reason:CCReason_Automatic]; 348 | } 349 | } 350 | 351 | - (void)performProcedureAnalysis:(NSObject *)procedure basicBlock:(NSObject *)basicBlock disasm:(DisasmStruct *)disasm { 352 | } 353 | 354 | - (void)updateProcedureAnalysis:(DisasmStruct *)disasm { 355 | } 356 | 357 | //Printing 358 | static inline int firstBitIndex(uint64_t mask) { 359 | for (int i=0, j=1; i<64; i++, j<<=1) { 360 | if (mask & j) { 361 | return i; 362 | } 363 | } 364 | return -1; 365 | } 366 | 367 | 368 | static inline RegClass regClassFromType(uint64_t type) { 369 | return (RegClass) firstBitIndex(DISASM_GET_REGISTER_CLS_MASK(type)); 370 | } 371 | 372 | static inline int regIndexFromType(uint64_t type) { 373 | return firstBitIndex(DISASM_GET_REGISTER_INDEX_MASK(type)); 374 | } 375 | 376 | - (NSObject *)buildMnemonicString:(DisasmStruct *)disasm inFile:(NSObject *)file { 377 | NSObject *services = _cpu.hopperServices; 378 | 379 | NSObject *line = [services blankASMLine]; 380 | if ((disasm->syntaxIndex & 2) != 0){ 381 | [line appendRawString:[NSString stringWithFormat:@"%04X:%04X ", [_cpu getCS], [_cpu getIP]]]; 382 | } 383 | NSString *mnemonic = @(disasm->instruction.mnemonic); 384 | [line appendMnemonic:mnemonic]; 385 | return line; 386 | } 387 | 388 | 389 | 390 | -(void)printRegisterIndex:(NSUInteger)regIdx ofClass:(RegClass)regCls line:(NSObject *)line disasm:(DisasmStruct*)disasm { 391 | if (disasm->syntaxIndex & 1){ 392 | [line appendRawString:@"%"]; 393 | } 394 | [line appendRegister:[_cpu registerIndexToString:regIdx 395 | ofClass:regCls 396 | withBitSize:16 397 | position:DISASM_LOWPOSITION 398 | andSyntaxIndex:disasm->syntaxIndex] 399 | ofClass:regCls 400 | andIndex:regIdx]; 401 | } 402 | 403 | -(void)printRegisterType:(DisasmOperandType)type line:(NSObject *)line disasm:(DisasmStruct*)disasm { 404 | RegClass regCls = regClassFromType(type); 405 | int regIdx = regIndexFromType(type); 406 | [self printRegisterIndex:regIdx ofClass:regCls line:line disasm:disasm]; 407 | } 408 | 409 | 410 | - (NSObject *)buildOperandString:(DisasmStruct *)disasm forOperandIndex:(NSUInteger)operandIndex inFile:(NSObject *)file raw:(BOOL)raw { 411 | if (operandIndex >= DISASM_MAX_OPERANDS) return nil; 412 | DisasmOperand *operand = disasm->operand + operandIndex; 413 | if (operand->type == DISASM_OPERAND_NO_OPERAND) return nil; 414 | 415 | // Get the format requested by the user 416 | ArgFormat format = [file formatForArgument:operandIndex atVirtualAddress:disasm->virtualAddr]; 417 | NSObject *services = _cpu.hopperServices; 418 | NSObject *line = [services blankASMLine]; 419 | [line setIsOperand:operandIndex startingAtIndex:0]; 420 | 421 | bool att = disasm->syntaxIndex & 1; 422 | bool memFilled = false; 423 | int regIdx = 0; 424 | 425 | if (operand->type & DISASM_OPERAND_CONSTANT_TYPE) { 426 | if (att){ 427 | [line appendRawString:@"$"]; 428 | } 429 | if (disasm->instruction.branchType != DISASM_BRANCH_NONE) { 430 | FORMAT(Format_Address); 431 | }else{ 432 | FORMAT(Format_Hexadecimal); 433 | } 434 | [line append:[file formatNumber:operand->immediateValue at:disasm->virtualAddr usingFormat:format andBitSize:operand->size]]; 435 | } 436 | else if (operand->type & DISASM_OPERAND_REGISTER_TYPE) { 437 | // Single register 438 | [self printRegisterType:operand->type line:line disasm:disasm]; 439 | }else if (operand->type & DISASM_OPERAND_MEMORY_TYPE) { 440 | if (!att){ 441 | [line appendRawString:intelPtrs[operand->size == 8 ? 0 : (operand->size == 32 ? 2 : 1)]]; 442 | } 443 | if (operand->segmentReg){ 444 | [self printRegisterIndex:operand->segmentReg ofClass:RegClass_X86_SEG line:line disasm:disasm]; 445 | [line appendRawString:@":"]; 446 | } 447 | //att disp 448 | if (att && operand->memory.displacement){ 449 | FORMAT(Format_Hexadecimal); 450 | [line append:[file formatNumber:operand->memory.displacement at:disasm->virtualAddr usingFormat:format andBitSize:16]]; 451 | if (!operand->memory.baseRegistersMask && !operand->memory.indexRegistersMask){ 452 | return line; 453 | } 454 | } 455 | [line appendRawString:att ? @"(" : @"["]; 456 | //base 457 | if (operand->memory.baseRegistersMask) { 458 | int regIdx = firstBitIndex(operand->memory.baseRegistersMask); 459 | [self printRegisterIndex:regIdx ofClass:RegClass_GeneralPurposeRegister line:line disasm:disasm]; 460 | memFilled = true; 461 | } 462 | //index 463 | if (operand->memory.indexRegistersMask){ 464 | if (memFilled){ 465 | [line appendRawString:att ? @"," : @"+"]; 466 | } 467 | regIdx = firstBitIndex(operand->memory.indexRegistersMask); 468 | [self printRegisterIndex:regIdx ofClass:RegClass_GeneralPurposeRegister line:line disasm:disasm]; 469 | if(operand->memory.scale>1){ 470 | [line appendRawString:att ? @"," : @"*"]; 471 | [line append:[file formatNumber:operand->memory.scale at:disasm->virtualAddr usingFormat:Format_Decimal andBitSize:16]]; 472 | } 473 | memFilled = true; 474 | } 475 | //intel disp 476 | if (!att && (operand->memory.displacement || !memFilled) ){ 477 | if (memFilled){ 478 | [line appendRawString:@"+"]; 479 | } 480 | FORMAT(Format_Hexadecimal); 481 | [line append:[file formatNumber:operand->memory.displacement at:disasm->virtualAddr usingFormat:format andBitSize:16]]; 482 | } 483 | [line appendRawString:att ? @")" : @"]"]; 484 | }else{ 485 | [line appendRawString:[NSString stringWithCString:operand->userString encoding:NSASCIIStringEncoding]]; 486 | } 487 | 488 | [line setIsOperand:operandIndex startingAtIndex:0]; 489 | 490 | return line; 491 | } 492 | 493 | - (NSObject *)buildCompleteOperandString:(DisasmStruct *)disasm inFile:(NSObject *)file raw:(BOOL)raw { 494 | NSObject *services = _cpu.hopperServices; 495 | 496 | NSObject *line = [services blankASMLine]; 497 | 498 | for (int op_index=0; op_index<=DISASM_MAX_OPERANDS; op_index++) { 499 | NSObject *part = [self buildOperandString:disasm forOperandIndex:op_index inFile:file raw:raw]; 500 | if (part == nil) break; 501 | if (op_index) [line appendRawString:@", "]; 502 | [line append:part]; 503 | } 504 | 505 | return line; 506 | } 507 | 508 | // Decompiler 509 | 510 | - (BOOL)canDecompileProcedure:(NSObject *)procedure { 511 | return NO; 512 | } 513 | 514 | - (Address)skipHeader:(NSObject *)basicBlock ofProcedure:(NSObject *)procedure { 515 | return basicBlock.from; 516 | } 517 | 518 | - (Address)skipFooter:(NSObject *)basicBlock ofProcedure:(NSObject *)procedure { 519 | return basicBlock.to; 520 | } 521 | 522 | - (ASTNode *)rawDecodeArgumentIndex:(int)argIndex 523 | ofDisasm:(DisasmStruct *)disasm 524 | ignoringWriteMode:(BOOL)ignoreWrite 525 | usingDecompiler:(Decompiler *)decompiler { 526 | return nil; 527 | } 528 | 529 | - (ASTNode *)decompileInstructionAtAddress:(Address)a 530 | disasm:(DisasmStruct *)d 531 | addNode_p:(BOOL *)addNode_p 532 | usingDecompiler:(Decompiler *)decompiler { 533 | return nil; 534 | } 535 | 536 | // Assembler 537 | 538 | - (NSData *)assembleRawInstruction:(NSString *)instr atAddress:(Address)addr forFile:(NSObject *)file withCPUMode:(uint8_t)cpuMode usingSyntaxVariant:(NSUInteger)syntax error:(NSError **)error { 539 | return nil; 540 | } 541 | 542 | - (BOOL)instructionCanBeUsedToExtractDirectMemoryReferences:(DisasmStruct *)disasmStruct { 543 | return NO; 544 | } 545 | 546 | - (BOOL)instructionOnlyLoadsAddress:(DisasmStruct *)disasmStruct { 547 | char* ins=disasmStruct->instruction.mnemonic; 548 | return ins[0]=='l' && (ins[1]=='e' || ins[1]=='d') && (ins[2]=='a' || ins[2]=='s'); 549 | } 550 | 551 | 552 | - (BOOL)instructionMayBeASwitchStatement:(DisasmStruct *)disasmStruct { 553 | return NO; 554 | } 555 | 556 | - (uint8_t)cpuModeForNextInstruction:(nonnull DisasmStruct *)disasmStruct { 557 | return 0; 558 | } 559 | 560 | 561 | - (BOOL)instructionConditionsCPUModeAtTargetAddress:(nonnull DisasmStruct *)disasmStruct resultCPUMode:(nonnull uint8_t *)cpuMode { 562 | return NO; 563 | } 564 | 565 | 566 | - (BOOL)instructionManipulatesFloat:(nonnull DisasmStruct *)disasmStruct { 567 | return NO; 568 | } 569 | 570 | 571 | 572 | 573 | @end 574 | -------------------------------------------------------------------------------- /Intel16CPU/Intel16CPU/OpComment.h: -------------------------------------------------------------------------------- 1 | // 2 | // OpComments.h 3 | // Intel16CPU 4 | // 5 | // Created by john on 22.07.17. 6 | // Copyright © 2017 bjfn. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "Intel16CPU.h" 12 | 13 | @interface OpComment : NSObject 14 | 15 | - (instancetype)init; 16 | +(NSString*)commentForOpcode:(DisasmStruct*)disasm CPU:(Intel16CPU*)cpu; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Intel16CPU/Intel16CPU/OpComment.mm: -------------------------------------------------------------------------------- 1 | // 2 | // OpComments.m 3 | // Intel16CPU 4 | // 5 | // Created by john on 22.07.17. 6 | // Copyright © 2017 bjfn. All rights reserved. 7 | // 8 | 9 | #import "OpComment.h" 10 | 11 | @implementation OpComment { 12 | NSDictionary* ports; 13 | NSDictionary* ints; 14 | } 15 | 16 | +(NSString*)commentForOpcode:(DisasmStruct*)disasm CPU:(Intel16CPU*)cpu { 17 | static OpComment *opc = nil; 18 | static dispatch_once_t onceToken; 19 | dispatch_once(&onceToken, ^{ 20 | opc = [[OpComment alloc] init]; 21 | }); 22 | switch (disasm->instruction.userData){ 23 | case X86_INS_OUT: 24 | return [opc getPortDescr:disasm CPU:cpu isIn:NO]; 25 | case X86_INS_IN: 26 | return [opc getPortDescr:disasm CPU:cpu isIn:YES]; 27 | case X86_INS_INT: 28 | return [opc getIntDescr:disasm CPU:cpu]; 29 | } 30 | return nil; 31 | } 32 | 33 | - (instancetype)init { 34 | if ( self == [super init]){ 35 | //load ports 36 | NSBundle *bundle = [NSBundle bundleForClass:[Intel16CPU class]]; 37 | NSString *fname=[bundle pathForResource:@"ports" ofType:@"json"]; 38 | NSData *data = [NSData dataWithContentsOfFile:fname]; 39 | if (data){ 40 | NSError *e = nil; 41 | ports = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&e]; 42 | if (!ports || e){ 43 | NSLog(@"Can't load ports %@", e); 44 | } 45 | }else{ 46 | NSLog(@"Can't load file%@", fname); 47 | } 48 | fname=[bundle pathForResource:@"ints" ofType:@"json"]; 49 | data = [NSData dataWithContentsOfFile:fname]; 50 | if (data){ 51 | NSError *e = nil; 52 | ints = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&e]; 53 | if (!ints || e){ 54 | NSLog(@"Can't load ports %@", e); 55 | } 56 | }else{ 57 | NSLog(@"Can't load file%@", fname); 58 | } 59 | } 60 | return self; 61 | } 62 | 63 | - (uint64_t)operandValue:(DisasmStruct*)disasm CPU:(Intel16CPU*)cpu intl:(int)intl att:(int)att { 64 | DisasmOperand *op=&disasm->operand[ (disasm->syntaxIndex & 1) ? att : intl]; 65 | uint64_t val = UNDEFINED_STATE; 66 | if (op->type & DISASM_OPERAND_CONSTANT_TYPE){ 67 | val = op->immediateValue; 68 | }else if (op->type & DISASM_OPERAND_REGISTER_TYPE){ 69 | val = [cpu getCapstoneReg:(x86_reg)op->userData[0]]; 70 | } 71 | return val; 72 | } 73 | 74 | - (NSString*)getPortDescr:(DisasmStruct*)disasm CPU:(Intel16CPU*)cpu isIn:(BOOL)isIn { 75 | uint64_t val = [self operandValue:disasm CPU:cpu intl:(isIn ? 1 : 0) att:(isIn ? 0 : 1)]; 76 | if (val==UNDEFINED_STATE || !ports){ 77 | return nil; 78 | } 79 | return [ports objectForKey:[NSString stringWithFormat:@"%04X", (uint32_t)val]]; 80 | } 81 | 82 | - (NSString*)getValue:(NSDictionary*)dict forReg:(x86_reg)reg CPU:(Intel16CPU*)cpu size:(int)size { 83 | if (!dict){ 84 | return nil; 85 | } 86 | uint64_t val = [cpu getCapstoneReg:reg]; 87 | if (val == UNDEFINED_STATE){ 88 | return nil; 89 | } 90 | static NSString *fmts[] = {@"%01X", @"%02X", @"%03X", @"%04X"}; 91 | return [dict objectForKey:[NSString stringWithFormat:fmts[size-1], val]]; 92 | } 93 | 94 | - (NSString*)getIntDescr:(DisasmStruct*)disasm CPU:(Intel16CPU*)cpu { 95 | uint64_t val = [self operandValue:disasm CPU:cpu intl:0 att:0]; 96 | if (val == UNDEFINED_STATE || !ints){ 97 | return nil; 98 | } 99 | NSDictionary* d = [ints objectForKey:[NSString stringWithFormat:@"%02X", (uint32_t)val]]; 100 | if (!d){ 101 | return nil; 102 | } 103 | NSString* ret = nil; 104 | if ((ret = [self getValue:[d objectForKey:@"AH"] forReg:X86_REG_AH CPU:cpu size:1])){ 105 | return ret; 106 | } 107 | if ((ret = [self getValue:[d objectForKey:@"AL"] forReg:X86_REG_AL CPU:cpu size:1])){ 108 | return ret; 109 | } 110 | if ((ret = [self getValue:[d objectForKey:@"AX"] forReg:X86_REG_AX CPU:cpu size:2])){ 111 | return ret; 112 | } 113 | if ((ret = [self getValue:[d objectForKey:@"BX"] forReg:X86_REG_BX CPU:cpu size:2])){ 114 | return ret; 115 | } 116 | if ((ret = [self getValue:[d objectForKey:@"CX"] forReg:X86_REG_CX CPU:cpu size:2])){ 117 | return ret; 118 | } 119 | return d[@"name"]; 120 | } 121 | 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /Intel16CPU/Intel16CPU/ports.json: -------------------------------------------------------------------------------- 1 | { 2 | "0000": "DMA channel 0 current address byte 0, then byte 1", 3 | "0001": "DMA channel 0 word count byte 0, then byte 1", 4 | "0002": "DMA channel 1 current address byte 0, then byte 1", 5 | "0003": "DMA channel 1 word count byte 0, then byte 1", 6 | "0004": "DMA channel 2 current address byte 0, then byte 1", 7 | "0005": "DMA channel 2 word count byte 0, then byte 1", 8 | "0006": "DMA channel 3 current address byte 0, then byte 1", 9 | "0007": "DMA channel 3 word count byte 0, then byte 1", 10 | "0008": "DMA channel 0-3 status register (see #P0001)", 11 | "0009": "DMA channel 0-3 write request register (see #P0003)", 12 | "000A": "DMA channel 0-3 mask register (see #P0004)", 13 | "000B": "DMA channel 0-3 mode register (see #P0005)", 14 | "000C": "DMA channel 0-3 clear byte pointer flip-flop register", 15 | "000D": "DMA channel 0-3 temporary register", 16 | "000E": "DMA channel 0-3 clear mask register", 17 | "000F": "DMA channel 0-3 write mask register (see #P0006)", 18 | "0018": "extended function register (see #P0007)", 19 | "001A": "extended function execute register", 20 | "0020": "PIC initialization command word ICW1 (see #P0010)", 21 | "0021": "PIC ICW2,ICW3,ICW4 immed after ICW1 to 0020 (see #P0011,#P0012,#P0013)", 22 | "0022": "PM2 Register Block", 23 | "0023": "chip set data", 24 | "0024": "chip set data", 25 | "0025": "82360 configuration data", 26 | "0026": "82335 RC2 roll compare register (if LOCK=0) (see #P0273)", 27 | "0028": "82335 CC0 address range compare register (if LOCK=0) (see #P0274)", 28 | "002A": "82335 CC1 address range compare register (if LOCK=0) (see #P0274)", 29 | "0027": "power management data", 30 | "002E": "index for data port (see #P0378)", 31 | "002F": "EPP command data", 32 | "0040": "PIT counter 0, counter divisor (XT, AT, PS/2)", 33 | "0041": "PIT counter 1, RAM refresh counter (XT, AT)", 34 | "0042": "PIT counter 2, cassette & speaker (XT, AT, PS/2)", 35 | "0043": "PIT mode port, control word register for counters 0-2 (see #P0380)", 36 | "0044": "PIT counter 3 (PS/2)", 37 | "0047": "PIT control word register counter 3 (PS/2, EISA)", 38 | "0048": "EISA PIT2 counter 3 (Watchdog Timer)", 39 | "0049": "EISA 8254 timer 2, not used (counter 4)", 40 | "004A": "EISA PIT2 counter 5 (CPU speed control)", 41 | "004B": "EISA PIT2 control word", 42 | "0050": "8530 serial communications chip", 43 | "0060": "KB controller data port or keyboard input buffer (ISA, EISA)", 44 | "0061": "KB controller port B control register (ISA, EISA)", 45 | "0062": "PPI (XT only) data port C (see #P0395)", 46 | "0063": "PPI (XT only) command mode register (see #P0397)", 47 | "0064": "keyboard controller read status (see #P0398,#P0399,#P0400)", 48 | "0065": "(Amstrad/Schneider PC1512) set 'DIP switch S2' RAM size setting", 49 | "0066": "configuration port (Olivetti M24 with model byte 0)", 50 | "0068": "(HP-Vectra) control buffer (HP commands) (see #P0408)", 51 | "0069": "(HP-Vectra) SVC (keyboard request SerViCe port)", 52 | "006A": "(HP-Vectra) Acknowledge (clear processing, done)", 53 | "006C": "(Human Interface Link = async. serial inputs 0-7)", 54 | "006B": "RAM enable/remap", 55 | "006D": "undocumented", 56 | "006E": "undocumented", 57 | "006F": "undocumented", 58 | "0070": "CMOS RAM index register port (ISA, EISA)", 59 | "0071": "CMOS RAM data port (ISA, EISA) (see #P0409)", 60 | "0072": "CMOS memory address, region 2 (256 bytes)", 61 | "0073": "CMOS memory data, region 2", 62 | "0074": "CMOS memory address, region 3 (256 bytes)", 63 | "0075": "CMOS memory data, region 3", 64 | "0076": "secondary CMOS RAM (IBM NVRAM) data byte", 65 | "0078": "NMI enable/disable", 66 | "007C": "HP-Vectra PIC 3 see at 0020 PIC 1", 67 | "007D": "HP-Vectra PIC 3 see at 0021 PIC 1", 68 | "0080": "Manufacturing Diagnostics port", 69 | "0081": "DMA channel 2 address byte 2", 70 | "0082": "DMA channel 3 address byte 2", 71 | "0083": "DMA channel 1 address byte 2", 72 | "0084": "extra page register", 73 | "0085": "extra page register", 74 | "0086": "extra page register", 75 | "0087": "DMA channel 0 address byte 2", 76 | "0088": "extra page register", 77 | "0089": "DMA channel 6 address byte 2", 78 | "008A": "DMA channel 7 address byte 2", 79 | "008B": "DMA channel 5 address byte 2", 80 | "008C": "extra page register", 81 | "008D": "extra page register", 82 | "008E": "extra page register", 83 | "008F": "DMA refresh page register", 84 | "0090": "Central arbitration control port", 85 | "0091": "Card selection feedback", 86 | "0092": "PS/2 system control port A (port B is at PORT 0061h) (see #P0415)", 87 | "0094": "system board enable/setup register (see #P0416)", 88 | "0095": "reserved", 89 | "0096": "adapter enable / setup register (see #P0417)", 90 | "0097": "reserved", 91 | "00A0": "PIC 2 same as 0020 for PIC 1", 92 | "00A1": "PIC 2 same as 0021 for PIC 1 except for OCW1 (see #P0418)", 93 | "00A8": "configuration register index (see #P0419)", 94 | "00A9": "configuration register data", 95 | "00AC": "configuration register FBh-FFh data", 96 | "00B2": "control", 97 | "00B3": "status", 98 | "00C0": "DMA channel 4 memory address bytes 1 and 0 (low) (ISA, EISA)", 99 | "00C2": "DMA channel 4 transfer count bytes 1 and 0 (low) (ISA, EISA)", 100 | "00C4": "DMA channel 5 memory address bytes 1 and 0 (low) (ISA, EISA)", 101 | "00C6": "DMA channel 5 transfer count bytes 1 and 0 (low) (ISA, EISA)", 102 | "00C8": "DMA channel 6 memory address bytes 1 and 0 (low) (ISA, EISA)", 103 | "00CA": "DMA channel 6 transfer count bytes 1 and 0 (low) (ISA, EISA)", 104 | "00CC": "DMA channel 7 memory address byte 0 (low), then 1 (ISA, EISA)", 105 | "00CE": "DMA channel 7 transfer count byte 0 (low), then 1 (ISA, EISA)", 106 | "00D0": "DMA channel 4-7 status register (ISA, EISA) (see #P0481)", 107 | "00D2": "DMA channel 4-7 write request register (ISA, EISA)", 108 | "00D4": "DMA channel 4-7 write single mask register (ISA, EISA) (see #P0484)", 109 | "00D6": "DMA channel 4-7 mode register (ISA, EISA) (see #P0485)", 110 | "00D8": "DMA channel 4-7 clear byte pointer flip-flop (ISA, EISA)", 111 | "00DA": "DMA channel 4-7 read temporary register (ISA, EISA)", 112 | "00DC": "DMA channel 4-7 clear mask register (ISA, EISA)", 113 | "00DE": "DMA channel 4-7 write mask register (ISA, EISA) (see #P0486)", 114 | "00E0": "index for accesses to data port", 115 | "00E1": "chip set data", 116 | "00E3": "error trace (bits 23-16 of address on last rising edge of ERS line)", 117 | "00E4": "error trace (bits 15-8 of address on last rising edge of ERS line)", 118 | "00E5": "error trace (see #P0490)", 119 | "00E7": "error trace (see #P0491)", 120 | "00EB": "???", 121 | "00ED": "???", 122 | "00F0": "disk controller", 123 | "00F2": "disk controller control port", 124 | "00F4": "disk controller status register", 125 | "00F5": "disk controller data port", 126 | "00F1": "math coprocessor reset (write 00h)", 127 | "00F8": "opcode transfer (CPU-coprocessor communication)", 128 | "00FA": "opcode transfer", 129 | "00FC": "opcode transfer", 130 | "0100": "POS register 0 Low adapter ID byte", 131 | "0101": "POS register 1 High adapter ID byte", 132 | "0102": "POS register 2 option select data byte 1 (see #P0492)", 133 | "0103": "POS register 3 option select data byte 2 (see #P0493)", 134 | "0104": "POS register 4 option select data byte 3", 135 | "0105": "POS register 5 option select data byte 4", 136 | "0106": "POS register 6 Low subaddress extension", 137 | "0107": "POS register 7 High subaddress extension", 138 | "010F": "leftmost character on display", 139 | "010E": "second character", 140 | "0108": "eighth character", 141 | "0140": "current SCSI data bus register", 142 | "0141": "initiator command register (see #P0496)", 143 | "0142": "mode register (see #P0497)", 144 | "0143": "target command register (see #P0498)", 145 | "0144": "current SCSI control register (see #P0499)", 146 | "0145": "DMA status register (see #P0500)", 147 | "0146": "input data register", 148 | "0147": "reset error/interrupt register", 149 | "0148": "pseudo-DMA register", 150 | "0149": "interrupt status register (see #P0508)", 151 | "014A": "configuration register 1 (see #P0509)", 152 | "014B": "configuration register 2, TMC-18C50/18C30/36C70 only (see #P0510)", 153 | "014C": "read FIFO data register", 154 | "014E": "FIFO data count register", 155 | "015C": "index for data port", 156 | "015D": "EPP command data", 157 | "0170": "read cycle timing register (see #P0536)", 158 | "0171": "write cycle timing register (see #P0537)", 159 | "0172": "internal ID register (see #P0538)", 160 | "0173": "control register (see #P0539)", 161 | "0175": "strap register (see #P0540)", 162 | "0176": "miscellaneous register (see #P0541)", 163 | "0178": "index selection for data port", 164 | "0179": "power management data", 165 | "01CE": "index register", 166 | "01CF": "data register", 167 | "01ED": "select internal register. Data to/from 01EF", 168 | "01EE": "???", 169 | "01EF": "register value", 170 | "01F0": "data register", 171 | "01F1": "error register (see #P0512)", 172 | "01F2": "sector count", 173 | "01F3": "sector number (CHS mode)", 174 | "01F4": "cylinder low (CHS mode)", 175 | "01F5": "cylinder high (CHS mode)", 176 | "01F6": "drive/head (see #P0513)", 177 | "01F7": "status register (see #P0514)", 178 | "01F8": "???", 179 | "0200": "Game port, eight identical addresses on some boards", 180 | "0201": "read joystick position and status (see #P0542)", 181 | "0208": "of ??? on the uPW48 (all showing zeros)", 182 | "0209": "EMS page register", 183 | "020A": "EMS page register", 184 | "0210": "latch expansion bus data", 185 | "0211": "clear wait, test latch", 186 | "0212": "Low byte data address", 187 | "0213": "0=enable, 1=disable expansion unit", 188 | "0214": "latch data (receiver card port)", 189 | "0215": "High byte of address, then Low byte (receiver card port)", 190 | "0218": "EMS page register", 191 | "0219": "EMS page register", 192 | "021A": "EMS page register", 193 | "0220": "Left speaker -- Status port", 194 | "0221": "Left speaker -- Data port", 195 | "0222": "Right speaker -- Status port", 196 | "0223": "Right speaker -- Data port", 197 | "0224": "mixer register address port (index) (see #P0543)", 198 | "0225": "mixer data port", 199 | "0226": "DSP reset", 200 | "0228": "FM music status port", 201 | "0229": "FM music data port", 202 | "022A": "DSP read data (voice I/O and Midi)", 203 | "022C": "DSP write data / write command", 204 | "022E": "DSP data available status (bit 7)", 205 | "022F": "Covox compatible speech I/O (via internal A/D converter,", 206 | "0238": "Command port", 207 | "0239": "Data port", 208 | "023A": "ID Port", 209 | "023C": "Command port", 210 | "023D": "Data port", 211 | "023E": "ID Port", 212 | "0240": "Mix Control register (see #P0545)", 213 | "0241": "Read Data", 214 | "0246": "IRQ Status Register (see #P0546)", 215 | "0248": "Timer Control Reg", 216 | "0249": "Timer Data (see #P0547)", 217 | "024B": "IRQ Control Register (0240 bit 6 = 1) (see #P0548)", 218 | "024F": "Register Controls (rev 3.4+)", 219 | "026E": "index for data port", 220 | "026F": "EPP command data", 221 | "0278": "speech data output via printer data port", 222 | "0279": "status port (see #P0658 at PORT 03BCh)", 223 | "027A": "control port (see #P0659 at PORT 03BCh)", 224 | "027B": "address strobe", 225 | "027C": "data strobe 0", 226 | "027D": "data strobe 1", 227 | "027E": "data strobe 2", 228 | "027F": "data strobe 3", 229 | "0280": "from 0280, 0288, 0290, 0298, 06A0, 06A8", 230 | "02A0": "of the 8255 on the EW-90xBN", 231 | "02E1": "GPIB (adapter 0)", 232 | "02E2": "data aquisition (adapter 0)", 233 | "02E3": "data aquisition (adapter 0)", 234 | "02E8": "display status", 235 | "02EA": "Lookup: DAC mask", 236 | "02EB": "Lookup: DAC read index", 237 | "02EC": "Lookup: DAC write index", 238 | "02ED": "Lookup: DAC data", 239 | "02F8": "transmitter holding register", 240 | "02F9": "divisor latch, high byte when DLAB=1", 241 | "02FA": "interrupt identification register", 242 | "02FB": "line control register", 243 | "02FC": "modem control register", 244 | "02FD": "line status register", 245 | "02FF": "scratch register", 246 | "0300": "address PROM (used to store Ethernet address, etc.)", 247 | "0310": "Register Data Port (RDP) (see #P0552,#P0553)", 248 | "0312": "Register Access Port (RAP) (selects register index for RDP and IDP)", 249 | "0314": "Reset", 250 | "0316": "ISA Bus Data Port (IDP)", 251 | "0318": "for vendor-specific use", 252 | "0320": "data register", 253 | "0321": "reset controller", 254 | "0322": "read DIPswitch setting on XT controller card", 255 | "0323": "write pattern to DMA and INT mask register", 256 | "0330": "data register", 257 | "0331": "status register (see #P0575)", 258 | "0332": "interrupt status register (see #P0579)", 259 | "0333": "(AHA-154xC+) diagnostic register", 260 | "0340": "MIDI Control (see #P0591)", 261 | "0341": "MIDI Transmit Data", 262 | "0342": "GF1 Page Register / Voice Select", 263 | "0343": "GF1/Global Register Select (see #P0593)", 264 | "0344": "GF1/Global Data Low Byte (16 bits)", 265 | "0345": "GF1/Global Data High Byte (8 bits)", 266 | "0346": "Mixer Data Port", 267 | "0347": "GF1 DRAM", 268 | "0348": "RAM (upper nybble only)", 269 | "0349": "year 0-99", 270 | "034A": "RAM last month storage", 271 | "034B": "RAM year storage (-80)", 272 | "034C": "RAM reserved", 273 | "034D": "RAM not used", 274 | "034E": "RAM not used", 275 | "034F": "RAM not used", 276 | "0350": "interrupt status register", 277 | "0351": "interrupt control register", 278 | "0352": "counter reset", 279 | "0353": "RAM reset", 280 | "0354": "status bit", 281 | "0355": "GO command", 282 | "0356": "standby interrupt", 283 | "0357": "test mode", 284 | "035A": "I/O channel setup (see #P0625)", 285 | "035B": "transfer mode setup (see #P0626)", 286 | "0370": "diskette Extra High Density controller board jumpers (AT)", 287 | "0371": "diskette controller status B (PS/2, PS/2 model 30)", 288 | "0372": "diskette controller DOR (Digital Output Register)", 289 | "0374": "diskette controller main status register", 290 | "0375": "diskette controller command/data register", 291 | "0376": "(2nd FIXED disk controller status/data register)", 292 | "0377": "(2nd FIXED disk controller drive address register)", 293 | "0378": "speech output via printer port", 294 | "0379": "status port (see #P0658 at PORT 03BCh)", 295 | "037A": "control port (see #P0659 at PORT 03BCh)", 296 | "037B": "bit 7: shadow RAM on/off (UniRAM adapter,according to c't 7/90)", 297 | "037C": "data strobe 0", 298 | "037D": "data strobe 1", 299 | "037E": "data strobe 2", 300 | "037F": "data strobe 3", 301 | "0380": "on adapter 8255(A5) port A: internal/external sensing (see #P0632)", 302 | "0381": "on adapter 8255(A5) port B: external modem interface (see #P0633)", 303 | "0382": "on adapter 8255(A5) port C: internal control (see #P0634)", 304 | "0383": "on adapter 8255(A5) mode initialization", 305 | "0384": "on adapter 8253 (programmable counter) counter 0:", 306 | "0385": "on adapter 8253 counter 1: LSB / MSB inactivity time-outs", 307 | "0386": "on adapter 8253 counter 2: LSB / MSB inactivity time-outs", 308 | "0387": "on adapter 8253 mode register (see #P0635)", 309 | "0388": "on adapter 8273 status register (see #P0636)", 310 | "0389": "on adapter 8273 (immediate) result register (see #P0644)", 311 | "038A": "on adapter 8273 transmit INT status (DMA/INT)", 312 | "038B": "on adapter 8273 receive INT status (DMA/INT)", 313 | "038C": "on adapter 8273 data: direct program control (DPC)", 314 | "038F": "configuration port (power on default=0, all features disabled)", 315 | "0390": "addresses of the 8255 on the EW-90xB", 316 | "0391": "(adapter 0) (XT)", 317 | "0392": "(adapter 0) (XT)", 318 | "0393": "(adapter 0) (XT)", 319 | "0398": "index for data port", 320 | "0399": "EPP command data", 321 | "03A0": "on adapter 8255(A5) port A: internal/external sensing (see #P0648)", 322 | "03A1": "on adapter 8255(A5) port B: external modem interface (see #P0649)", 323 | "03A2": "on adapter 8255(A5) port C: internal control (see #P0650)", 324 | "03A3": "on adapter 8255(A5) mode initialization", 325 | "03A4": "on adapter 8253 (programmable counter) counter 0:", 326 | "03A5": "on adapter 8253 counter 1: LSB / MSB inactivity time-outs", 327 | "03A6": "on adapter 8253 counter 2: LSB / MSB inactivity time-outs", 328 | "03A7": "on adapter 8253 mode register (see #P0651)", 329 | "03A8": "on adapter 8251: data (see #P0652)", 330 | "03A9": "on adapter 8251: command/mode/USART status register (see #P0653)", 331 | "03B0": "same as 03B4", 332 | "03B1": "same as 03B5", 333 | "03B2": "same as 03B4", 334 | "03B3": "same as 03B5", 335 | "03B4": "MDA CRT index register (MDA/mono EGA/mono VGA)", 336 | "03B5": "MDA CRT data register (MDA/mono EGA/mono VGA) (see #P0654,#P0708)", 337 | "03B6": "same as 03B4h", 338 | "03B7": "same as 03B5h", 339 | "03B8": "MDA mode control register (see #P0655)", 340 | "03B9": "reserved for color select register on color adapter", 341 | "03BA": "CRT status register (see #P0656)", 342 | "03BB": "light pen strobe reset (on any value)", 343 | "03BC": "data port", 344 | "03BD": "status port (see #P0658)", 345 | "03BE": "control port (see #P0659)", 346 | "03BF": "configuration switch register (see #P0660)", 347 | "03C0": "ATC index/data register", 348 | "03C1": "(VGA) ATC index/data read register", 349 | "03C2": "input status 0 register (see #P0668)", 350 | "03C3": "(VGA) video subsystem enable (see also PORT 46E8h)", 351 | "03C4": "EGA TS index register", 352 | "03C5": "EGA TS data register", 353 | "0011": "9 = 15-bit, 1 pixel/VCLK", 354 | "0111": "12 = 640x480x24-bit (packed), 1 pixel/3 DCLKs (Trio32 only)", 355 | "1101": "13 = 24-bit, 1 pixel/VCLK", 356 | "03C6": "(VGA, MCGA) PEL mask register (default FFh)", 357 | "03C7": "(VGA,MCGA,CEG-VGA) PEL address register (read mode)", 358 | "03C8": "(VGA,MCGA) PEL address register (write mode)", 359 | "03C9": "(VGA,MCGA) PEL data register", 360 | "03CA": "EGA graphics 2 position register", 361 | "03CB": "(ET4000/W32) GDC segment select register 2 ('key' protected?)", 362 | "03CC": "EGA graphics 1 position register", 363 | "03CD": "(ET3000, ET4000, ET4000/W32) GDC segment select ('key' protected)", 364 | "03CE": "EGA GDC index register", 365 | "03CF": "EGA GDC data register (see #P0700)", 366 | "03D0": "same as PORT 03D4h", 367 | "03D1": "same as PORT 03D5h", 368 | "03D2": "same as PORT 03D4h", 369 | "03D3": "same as PORT 03D5h", 370 | "03D4": "CRT (6845) register index (CGA/MCGA/color EGA/color VGA)", 371 | "03D5": "CRT (6845) data register (CGA/MCGA/color EGA/color VGA) (see #P0708)", 372 | "03D6": "same as 03D4", 373 | "03D7": "same as 03D5", 374 | "03D8": "CGA mode control register (except PCjr) (see #P0817)", 375 | "03D9": "CGA palette register (see #P0819)", 376 | "03DA": "CGA status register (see #P0818)", 377 | "03DB": "clear light pen latch (not MCGA)", 378 | "03DC": "(not MCGA) preset light pen latch", 379 | "03DD": "(MCGA) Extended mode control register", 380 | "03DE": "(MCGA) reserved", 381 | "03DF": "(MCGA) reserved", 382 | "03E0": "index for data register", 383 | "03E1": "CardBus registers", 384 | "03E2": "index for data register", 385 | "03E3": "CardBus registers", 386 | "03F0": "diskette controller status A (PS/2) (see #P0857)", 387 | "03F1": "diskette controller status B (PS/2) (see #P0860)", 388 | "03F2": "diskette controller DOR (Digital Output Register) (see #P0862)", 389 | "03F3": "tape drive register (on the 82077AA)", 390 | "03F4": "diskette controller main status register (see #P0865)", 391 | "03F5": "diskette command/data register 0 (ST0) (see #P0867)", 392 | "03F6": "reserved on FDC", 393 | "03F7": "harddisk controller (see #P0872)", 394 | "03F8": "serial port, transmitter holding register (THR), which contains the", 395 | "03F9": "divisor latch high byte (DLM) when DLAB=1 (see #P0876)", 396 | "03FA": "interrupt identification register (see #P0878)", 397 | "03FB": "line control register (LCR) (see #P0880)", 398 | "03FC": "modem control register (see #P0881)", 399 | "03FD": "line status register (LSR) (see #P0882)", 400 | "03FE": "modem status register (MSR) (see #P0883)", 401 | "03FF": "scratch register (SCR)", 402 | "0401": "DMA channel 0 word count byte 2 (high)", 403 | "0403": "DMA channel 1 word count byte 2 (high)", 404 | "0405": "DMA channel 2 word count byte 2 (high)", 405 | "0407": "DMA channel 3 word count byte 2 (high)", 406 | "040A": "extended DMA chaining mode register, channels 0-3 (see #P0884)", 407 | "040B": "DMA extended mode register for channels 0-3 (see #P0886)", 408 | "0410": "CH0 scatter/gather command (see #P0888)", 409 | "0411": "CH1 scatter/gather command", 410 | "0412": "CH2 scatter/gather command", 411 | "0413": "CH3 scatter/gather command", 412 | "0414": "CH4 scatter/gather command", 413 | "0415": "CH5 scatter/gather command", 414 | "0416": "CH6 scatter/gather command", 415 | "0417": "CH7 scatter/gather command (see #P0888)", 416 | "0418": "CH0 scatter/gather status (see #P0889)", 417 | "0419": "CH1 scatter/gather status", 418 | "041A": "CH2 scatter/gather status", 419 | "041B": "CH3 scatter/gather status", 420 | "041C": "CH4 scatter/gather status", 421 | "041D": "CH5 scatter/gather status", 422 | "041E": "CH6 scatter/gather status", 423 | "041F": "CH7 scatter/gather status (see #P0889)", 424 | "0420": "CH0 scatter/gather descriptor table address", 425 | "0424": "CH1 scatter/gather descriptor table address", 426 | "0428": "CH2 scatter/gather descriptor table address", 427 | "042C": "CH3 scatter/gather descriptor table address", 428 | "0430": "CH4 scatter/gather descriptor table address", 429 | "0434": "CH5 scatter/gather descriptor table address", 430 | "0438": "CH6 scatter/gather descriptor table address", 431 | "043C": "CH7 scatter/gather descriptor table address", 432 | "040D": "chip stepping level", 433 | "040E": "test register 1", 434 | "040F": "test register 2", 435 | "0461": "Extended NMI status/control register (see #P0890)", 436 | "0462": "Software NMI register. writing to this register causes an NMI if", 437 | "0464": "bus master status latch register (slots 1-16)", 438 | "0481": "DMA channel 2 address byte 3 (high)", 439 | "0482": "DMA channel 3 address byte 3 (high)", 440 | "0483": "DMA channel 1 address byte 3 (high)", 441 | "0487": "DMA channel 0 address byte 3 (high)", 442 | "0489": "DMA channel 6 address byte 3 (high)", 443 | "048A": "DMA channel 7 address byte 3 (high)", 444 | "048B": "DMA channel 5 address byte 3 (high)", 445 | "04C6": "DMA channel 5 word count byte 2 (high)", 446 | "04CA": "DMA channel 6 word count byte 2 (high)", 447 | "04CE": "DMA channel 7 word count byte 2 (high)", 448 | "04D0": "IRQ 0-7 interrupt edge/level registers (see #P0891)", 449 | "04D1": "IRQ 8-15 interrupt edge/level registers (see #P0892)", 450 | "04D4": "DMA chaining status", 451 | "04D6": "DMA extended mode register for channels 4-7 (see #P0894)", 452 | "04E0": "channel 0 stops if DMA transfer reaches specified address", 453 | "04E4": "channel 1", 454 | "04E8": "channel 2", 455 | "04EC": "channel 3", 456 | "04F4": "channel 5", 457 | "04F8": "channel 6", 458 | "04FC": "channel 7", 459 | "0530": "address select (see #P0895)", 460 | "0531": "data (selected by PORT 0530h)", 461 | "0532": "status", 462 | "0533": "PIO data", 463 | "0534": "register select (index) (see #P0895)", 464 | "0535": "data register (selected by PORT 0534h)", 465 | "0536": "(CS4231A) status register", 466 | "0537": "(CS4231A) PIO data register", 467 | "0601": "system control (see #P0914)", 468 | "0628": "PC network (adapter 2)", 469 | "063E": "always reads 42h if WinTel.VXD is loaded (installation check)", 470 | "063F": "watchdog/scratchpad (see #P0916)", 471 | "0678": "(when ECR bits 7-5=010) standard parallel port data FIFO (see #P0918)", 472 | "0679": "(when ECR bits 7-5=111) ECP configuration B (see #P0922)", 473 | "067A": "extended control register (ECR) (see #P0923)", 474 | "0680": "Microchannel POST Diagnostic", 475 | "0681": "secondary MCA POST diagnostic", 476 | "06E8": "CRT control: horizontal displayed", 477 | "0746": "board version (rev 3.7+)", 478 | "0778": "(when ECR bits 7-5=010) standard parallel port data FIFO (see #P0918)", 479 | "0779": "(when ECR bits 7-5=111) ECP configuration B (see #P0922)", 480 | "077A": "extended control register (ECR) (see #P0923)", 481 | "07BC": "(when ECR bits 7-5=010) standard parallel port data FIFO (see #P0918)", 482 | "07BD": "(when ECR bits 7-5=111) ECP configuration B (see #P0922)", 483 | "07BE": "extended control register (ECR) (see #P0923)", 484 | "0A24": "Token Ring (adapter 2)", 485 | "0A79": "Plug-and-Play data writes", 486 | "0AD6": "index for accesses to data port (see #P0924)", 487 | "0AD7": "data port", 488 | "0AE8": "CRT control: horizontal sync start", 489 | "0C00": "page register to write to SRAM or I/O", 490 | "0C80": "bit 7: unused (0)", 491 | "0C81": "bits 7-5: manufacturer ID, second compressed ASCII char (low)", 492 | "0C82": "reserved for manufacturer's use", 493 | "0C83": "bits 7-3: reserved for manufacturer's use", 494 | "0CF8": "configuration address port (see #P0944)", 495 | "0CFC": "configuration data port (when PORT 0CF8h bit 31 is set)", 496 | "0CFA": "Forward Register (selects target bus number)", 497 | "0CF9": "reboot system, optionally selecting de-turbo mode (see #P0946)", 498 | "0CFB": "specify which PCI access mechanism is to be enabled", 499 | "0EE8": "CRT control: horizontal sync width", 500 | "0F8D": "\"MCBase\" base register (see #P0948)", 501 | "0F8E": "\"MCIdx\" index register (see #P0949)", 502 | "0F8F": "\"MCData\" data register", 503 | "1010": "write 01h to map screen buffer 1 into memory at F000h:0000h", 504 | "1020": "write 01h to map screen buffer 2 into memory at F000h:0000h", 505 | "1030": "write 01h to map screen buffer 3 into memory at F000h:0000h", 506 | "1040": "write 01h to map screen buffer 4 into memory at F000h:0000h", 507 | "12E8": "CRT control: vertical total", 508 | "13C6": "Compaq video status??? (see #P0978)", 509 | "16E8": "CRT control: vertical displayed", 510 | "1AE8": "CRT control: vertical sync start", 511 | "0010": "- erase all registers", 512 | "01AA": "D15..D0 write register with address A5..A0", 513 | "10AA": "- read registers starting with address A5..A0", 514 | "11AA": "- erase register with address A5..A0", 515 | "1C65": "bit 6: operating on battery power", 516 | "1C80": "EISA Video ID", 517 | "1C84": "EISA Video expansion board control (see #P1016)", 518 | "1C85": "EISA Setup control", 519 | "1C88": "EISA Video Programmable Option Select 0", 520 | "1C89": "EISA Video Programmable Option Select 1-7", 521 | "1C81": "bits 7-5: manufacturer ID, second compressed ASCII char (low)", 522 | "1C82": "bits 7-4: first hex digit of product type", 523 | "1C83": "bits 7-4: third hex digit of product type", 524 | "1EE8": "CRT control: vertical sync width", 525 | "1EEC": "display power and other controls", 526 | "2065": "??? (84h seen)", 527 | "210C": "byte data", 528 | "22E8": "CRT control: display control", 529 | "2465": "current battery power level", 530 | "27C6": "LCD timeout in minutes", 531 | "2C84": "configuration flags (see #P1016)", 532 | "3510": "status word", 533 | "3512": "basic status", 534 | "3513": "interrupt status", 535 | "3518": "status word", 536 | "351A": "basis status", 537 | "351B": "interrupt status", 538 | "36EE": "FIFO option", 539 | "3C80": "EISA Video ID", 540 | "3C84": "EISA Video expansion board control", 541 | "3C85": "EISA Setup control", 542 | "3C88": "EISA Video Programmable Option Select 0", 543 | "3C89": "EISA Video Programmable Option Select 1-7", 544 | "42E1": "GPIB (adapter 2)", 545 | "42E8": "Misc. control: Subsystem Status (see #P1018)", 546 | "42EC": "???", 547 | "42ED": "???", 548 | "42EE": "memory boundary", 549 | "42EF": "???", 550 | "46E8": "Misc. control: enable flags / select ROM page (8514/A) (see #P1020)", 551 | "46EE": "???", 552 | "4AE8": "CRT control: Advanced function control (see also #P1022)", 553 | "4AEE": "???", 554 | "4C84": "configuration flags (see #P1016)", 555 | "52E8": "Extended Configuration Register 0", 556 | "52EE": "scratch register 0: Video ROM address", 557 | "56E8": "Extended Configuration Register 1", 558 | "56EE": "scratchpad", 559 | "5AE8": "Extended Configuration Register 2", 560 | "5AEE": "???", 561 | "5C80": "EISA Video ID", 562 | "5C84": "EISA Video expansion board control", 563 | "5C85": "EISA Setup control", 564 | "5C88": "EISA Video Programmable Option Select 0", 565 | "5C89": "EISA Video Programmable Option Select 1", 566 | "5C8A": "EISA Video Programmable Option Select 2", 567 | "5C8B": "EISA Video Programmable Option Select 3", 568 | "5C8C": "EISA Video Programmable Option Select 4", 569 | "5C8D": "EISA Video Programmable Option Select 5", 570 | "5C8E": "EISA Video Programmable Option Select 6", 571 | "5C8F": "EISA Video Programmable Option Select 7", 572 | "5EE8": "Extended Configuration Register 3", 573 | "5EEE": "Memory Aperture Configuration (see #P1023)", 574 | "62E1": "GPIB (adapter 3)", 575 | "6AEE": "maximum wait states (see #P1024)", 576 | "6C80": "EISA Video ID (see PORT 1C80h-1C83h)", 577 | "6C84": "EISA Video expansion board control", 578 | "6C85": "EISA Setup control", 579 | "6C88": "EISA Video Programmable Option Select 0", 580 | "6C89": "EISA Video Programmable Option Select 1", 581 | "6C8A": "EISA Video Programmable Option Select 2", 582 | "6C8B": "EISA Video Programmable Option Select 3", 583 | "6C8C": "EISA Video Programmable Option Select 4", 584 | "6C8D": "EISA Video Programmable Option Select 5", 585 | "6C8E": "EISA Video Programmable Option Select 6", 586 | "6C8F": "EISA Video Programmable Option Select 7", 587 | "72EE": "high bits of video buffer starting offset", 588 | "76EE": "display pitch", 589 | "7AEE": "extended graphics engine configuration (see #P1025)", 590 | "7C80": "EISA Video ID", 591 | "7C84": "EISA Video expansion board control", 592 | "7C85": "EISA Setup control", 593 | "7C88": "EISA Video Programmable Option Select 0", 594 | "7C89": "EISA Video Programmable Option Select 1-7", 595 | "7EEE": "right edge of bounding box for points written via Line Draw register", 596 | "82E1": "GPIB (adapter 4)", 597 | "82E8": "drawing control: current Y position", 598 | "82EA": "control: current Y position 2", 599 | "83C6": "color palette pixel mask", 600 | "83C7": "color palette state", 601 | "83C8": "color palette write-mode index", 602 | "83C9": "color palette data (three bytes)", 603 | "83D0": "\"DR00\" BitBlt offset register (see #P1026)", 604 | "87D0": "\"DR01\" BitBlt pattern ROP register (see #P1027)", 605 | "8BD0": "\"DR02\" BitBlt background color register (see #P1028)", 606 | "8FD0": "\"DR03\" BitBlt foreground color register (see #P1029)", 607 | "93D0": "\"DR04\" BitBlt control register (see #P1030)", 608 | "97D0": "\"DR05\" BitBlt source register (see #P1031)", 609 | "9BD0": "\"DR06\" BitBlt destination register (see #P1032)", 610 | "9FD0": "\"DR07\" BitBlt command register (see #P1033)", 611 | "86E8": "drawing control: current X position (bits 11-0)", 612 | "86EA": "drawing control: current X position 2 (bits 11-0)", 613 | "8AE8": "drawing control: destination Y position / axial step constant", 614 | "8AEA": "drawing control: destination Y position 2 / axial step constant 2", 615 | "8C84": "configuration flags (see #P1016)", 616 | "8EE8": "drawing control: destination X position / axial step constant", 617 | "8EEA": "drawing control: destination X position 2 / diagonal step constant 2", 618 | "8EEE": "read extended graphics configuration (see #P1025)", 619 | "92E8": "drawing control: Bresenham error term (bits 13-0)", 620 | "92EA": "drawing control: Bresenham error term 2 (bits 13-0)", 621 | "96E8": "enter WD Enhanced Mode", 622 | "96EA": "drawing control: major axis pixel count 2 (bits 11-0)", 623 | "9AE8": "drawing control: graphic processor status (see #P1035)", 624 | "9AEA": "drawing command 2 (see #P1038)", 625 | "9AEE": "linedraw index register (specifies interpretation of PORT FEEEh)", 626 | "9C84": "configuration flags (see #P1016)", 627 | "9EE8": "short line vector transfer (see #P1040)", 628 | "A2E1": "GPIB (adapter 5)", 629 | "A2E8": "drawing control: background color", 630 | "A2EE": "line drawing options (see #P1041)", 631 | "A3D0": "\"DR08\" cursor control register (see #P1042)", 632 | "A7D0": "\"DR09\" cursor color register (see #P1043)", 633 | "ABD0": "\"DR0A\" reserved", 634 | "AFD0": "\"DR0B\" cursor position register (see #P1044)", 635 | "B3D0": "\"DR0C\" cursor base address (see #P1045)", 636 | "B7D0": "\"DR0D\" reserved", 637 | "BBD0": "\"DR0E\" reserved", 638 | "BFD0": "\"DR0F\" reserved", 639 | "A6E8": "drawing control: foreground color", 640 | "AAE8": "drawing control: write mask", 641 | "AEE8": "drawing control: read mask", 642 | "AFFF": "plane 0-3 system latch (video register)", 643 | "B2E8": "drawing control: color compare", 644 | "B2EE": "???", 645 | "B6E8": "drawing control: background mix (see #P1046)", 646 | "B6EE": "???", 647 | "BAE8": "drawing control: foreground mix (see #P1046)", 648 | "BAEE": "???", 649 | "BEE8": "drawing control: multi-function control (see #P1048)", 650 | "C2E1": "GPIB (adapter 6)", 651 | "C2EE": "???", 652 | "C6EE": "short-stroke vector", 653 | "CAEE": "???", 654 | "CEEE": "datapath configuration (see #P1050)", 655 | "D2EE": "???", 656 | "DAEE": "left edge of \"scissors\" drawing area (bits 11-0)", 657 | "DEEE": "top edge of \"scissors\" drawing area (bits 11-0)", 658 | "E2E1": "GPIB (adapter 7)", 659 | "E2E8": "drawing control: pixel data transfer", 660 | "E2EA": "drawing control: pixel data transfer (S3 801+) for 32-bit transfers", 661 | "E2EE": "bottom edge of \"scissors\" drawing area (bits 11-0)", 662 | "E6EE": "right edge of \"scissors\" drawing area (bits 11-0)", 663 | "EAE8": "pattern Y coordinate (bits 11-0)", 664 | "EAEA": "pattern X coordinate (bits 11-0)", 665 | "EDC0": "emulated I/O address for video/serial activity status check", 666 | "EDC1": "emulated I/O address for idle port", 667 | "FEEE": "direct line-draw register", 668 | "8514": "ports found in FractInt v18.0 source file FR8514A.ASM", 669 | "073A": "more to come!" 670 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, Br. John Fn None 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HopperDos 2 | -------------------------------------------------------------------------------- /scripts/DosExportSym.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | doc = Document.getCurrentDocument() 4 | seg = doc.getSegment(0) 5 | sex = [x.getStartingAddress() for x in seg.getSectionsList()] 6 | 7 | 8 | def secAddr(addr, ofs=None): 9 | s = max([x for x in sex if x <= addr]) >> 4 10 | if ofs is None: 11 | ofs = addr-(s << 4) 12 | return "{:04X}:{:04X}".format(s, ofs) 13 | 14 | out = {} 15 | names = {} 16 | for x in seg.getSectionsList(): 17 | nm = x.getName().split()[-1] 18 | if nm in names: 19 | names[nm] += 1 20 | else: 21 | names[nm] = 0 22 | out["__SEG__"+nm+str(names[nm])] = "0x{:04X}".format(x.getStartingAddress() >> 4) 23 | 24 | for x in seg.getLabelsList(): 25 | addr = doc.getAddressForName(x) 26 | out[x] = secAddr(addr) 27 | 28 | file = Document.askFile("save symbols", None, True) 29 | with open(file, "w") as f: 30 | json.dump(out, f, indent=2, separators=(',', ': ')) 31 | -------------------------------------------------------------------------------- /scripts/DosImportSym.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | file = Document.askFile("load symbols", None, False) 4 | with open(file) as f: 5 | nms = json.load(f) 6 | 7 | doc = Document.getCurrentDocument() 8 | 9 | for x in nms: 10 | adr = nms[x].split(':') 11 | if len(adr) != 2: 12 | continue 13 | lin = (int(adr[0], 16) << 4) + int(adr[1], 16) 14 | doc.setNameAtAddress(lin, x) 15 | -------------------------------------------------------------------------------- /tools/mk_ints.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import getopt 4 | import os 5 | import json 6 | from collections import OrderedDict 7 | 8 | 9 | class App: 10 | MODE_INIT = -1 11 | MODE_WAIT = 0 12 | MODE_INT = 1 13 | MODE_PARAMS = 2 14 | CATS = "BCDEHMSTV" 15 | HEX = "0123456789ABCDEF" 16 | 17 | def __init__(self): 18 | self.mode = self.MODE_WAIT 19 | self.curInt = None 20 | self.path = None 21 | 22 | def ishex(self, string): 23 | for x in string: 24 | if not x in self.HEX: 25 | return False 26 | return True 27 | 28 | def wait(self, line, obj): 29 | if not line.startswith("--------"): 30 | return 31 | if len(line) < 9 or line[8] not in self.CATS: 32 | return 33 | self.mode = self.MODE_INT 34 | 35 | def saveInt(self, obj): 36 | self.mode = self.MODE_WAIT 37 | if not self.curInt: 38 | return 39 | o = self.curInt 40 | self.curInt = None 41 | i = o['int'] 42 | if i.endswith('h'): 43 | i = i[:-1] 44 | if o['cond'] is None: 45 | if i not in obj: 46 | obj[i] = {'name': o['name'] + o['params']} 47 | return 48 | if i not in obj or isinstance(obj[i], basestring): 49 | obj[i] = {} 50 | reg = o['cond'][0] 51 | if reg not in obj[i]: 52 | obj[i][reg] = OrderedDict() 53 | val = o['cond'][1] 54 | obj[i][reg][val] = (o['name'] + "\n" + o['params']).strip().replace("\r\n\n", "\n") 55 | 56 | def readInt(self, line, obj): 57 | if not line.startswith("INT "): 58 | self.saveInt(obj) 59 | return 60 | words = line.split() 61 | inter = words[1] 62 | self.curInt = {'int': inter, 'name': '-'.join(line.split('-')[1:]).strip(), 'cond': None, 'params': ""} 63 | self.mode = self.MODE_PARAMS 64 | 65 | def params(self, line, obj): 66 | if not self.curInt or (line[0] != "\t" and line.split(':')[0] != "Return"): 67 | self.saveInt(obj) 68 | return 69 | if len(self.curInt['params']) == 0: 70 | while True: 71 | if self.curInt['cond'] is not None or line[0] != '\t': 72 | break 73 | words = line.split() 74 | if len(words) != 3: 75 | break 76 | val = words[2] 77 | if val.endswith('h'): 78 | val = val[:-1] 79 | if words[1] != '=' or not self.ishex(val): 80 | break 81 | self.curInt['cond'] = (words[0], val) 82 | return 83 | self.curInt['params'] = line 84 | else: 85 | self.curInt['params'] += "\n" + line 86 | 87 | def parseInts(self, line, obj): 88 | if line is None: 89 | with open(os.path.join(self.path, "OVERVIEW.LST")) as f: 90 | for line in f: 91 | if not line.startswith("INT "): 92 | continue 93 | words = line.split() 94 | obj[words[1]] = {'name': ' '.join(words[3:])} 95 | return 96 | 97 | if line.startswith("--------"): 98 | self.saveInt(obj) 99 | if self.mode == self.MODE_WAIT: 100 | self.wait(line, obj) 101 | elif self.mode == self.MODE_INT: 102 | self.readInt(line, obj) 103 | elif self.mode == self.MODE_PARAMS: 104 | self.params(line, obj) 105 | 106 | def parsePorts(self, line, obj): 107 | if line is None or not self.ishex(line[0]): 108 | return 109 | words = line.split() 110 | if len(words) < 3 or len(words[0]) < 4: 111 | return 112 | key = words[0][:4] 113 | if not self.ishex(key) or key in obj: 114 | return 115 | obj[key] = ' '.join(words[2:]) 116 | 117 | def parseFiles(self, file, outfile, proc): 118 | ext = 'A' 119 | data = OrderedDict() 120 | path = os.path.join(self.path, file) 121 | self.mode = self.MODE_INIT 122 | proc(None, data) 123 | while os.path.exists(path + ext): 124 | fname = path + ext 125 | ext = chr(ord(ext) + 1) 126 | print "processing file " + fname 127 | with open(fname, "r") as f: 128 | for line in f: 129 | proc(line, data) 130 | with open(outfile, "w") as f: 131 | json.dump(data, f, indent=2, separators=(',', ': ')) 132 | 133 | def run(self): 134 | try: 135 | opts, args = getopt.getopt(sys.argv, 'h', ["help"]) 136 | for o, a in opts: 137 | if o in ("-h", "--help"): 138 | return self.usage() 139 | 140 | self.path = args[1] if len(args) > 1 else os.path.realpath(__file__) 141 | self.parseFiles("INTERRUP.", "ints.json", self.parseInts) 142 | self.parseFiles("PORTS.", "ports.json", self.parsePorts) 143 | except getopt.GetoptError as e: 144 | print str(e) 145 | return self.usage() 146 | except Exception as e: 147 | print str(e) 148 | return 2 149 | 150 | def usage(self): 151 | print """ 152 | mk_ints.py - convert Ralf Brown's interrupt list to xml. 153 | """ 154 | return 1 155 | 156 | 157 | if __name__ == "__main__": 158 | sys.exit(App().run()) 159 | --------------------------------------------------------------------------------